PFQuery first returning 6 items then 3 in a UITableViewController - uitableview

He everyone,
Im pulling my hears out for a whole day for the following issue. My back-end is in Parse and i am doing a query on my table "events" in a UITableViewController. The problem is that the query returns the complete data in the ViewDidLoad but not in my tableView method. In my tableView im only getting 3 items returned. Im aware of that parse query doing a Asynchronously call but why its returning 3 items?
I would be gratefull if somebody can help me out here.
Here is my code:
class EventOverViewController: UITableViewController {
var events:Array = [AnyObject]();
var imageContainer : UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None;
self.retrieveInfoFromParse();
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.events.count
}
func queryForTable() -> PFQuery {
let getEvents = PFQuery(className:"Event");
return getEvents;
}
func retrieveInfoFromParse(){
self.queryForTable().findObjectsInBackgroundWithBlock { (objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
for object in objects! {
self.events.append(object);
}
//RETURNING 6 ITEMS
print(self.events);
self.tableView.reloadData();
}
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 230;
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("EventCell", forIndexPath:indexPath) as! EventTableViewCell
let eventData = self.events[indexPath.row];
//ONLY returning 3 ITEMS, WHY?
print(eventData);
return cell
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
let destinationVC = segue.destinationViewController as! RootMainViewController
var secondEventData : Event!
secondEventData = self.events[indexPath.row] as! Event;
destinationVC.title = secondEventData.eventName;
destinationVC.event = secondEventData;
}
}

Related

Retrieving firebase children and populating them in a UITableView

Trying to query firebase children and retrieve a snapshot array of their data into a tableview. Not sure if I am implementing this correctly, but I am not the getting a runtime error. However, my tableview is just white with no objects displaying. Some feedback would be helpful. Thanks.
Here is my FB JSON tree structure
Here is my User class (var userList = User)
class CDetailTableViewController: UITableViewController {
static var imageCache = NSCache<AnyObject, UIImage>()
var userList = [User]()
var ref = FIREBASE.FBDataReference().ref
var refHandle: UInt!
override func viewDidLoad() {
super.viewDidLoad()
ref = FIREBASE.FBLink().FBref
configureCell()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return userList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! CDetailTableViewCell
cell.priceLabel?.text = userList[indexPath.row].priceLabel
cell.titleLabel?.text = userList[indexPath.row].titleLabel
cell.itemPhoto?.image = userList[indexPath.row].objectImage
return cell
}
func configureCell(){
let ref = FIRDatabase.database().reference()
let userID = FIRAuth.auth()?.currentUser?.uid
refHandle = ref.child("Enterpriser Listings").child("Sell Old Stuff - Listings").child(userID!).observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String : AnyObject] {
print("get dictionary")
print(dictionary)
let user = User()
user.setValuesForKeys(dictionary)
self.userList.append(user)
// Get user value
DispatchQueue.main.async {
print("reloaded")
self.tableView.reloadData()
}
}
})
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
May be the problem is with your Firebase reference, try like this way.
ref.child("Enterpriser Listings").child("Sell Old Stuff - Listings").observe(.value, with: { (snapshot:FIRDataSnapshot) in
var users = [User]()
for child in snapshot.children {
print("\((sweet as! FIRDataSnapshot).value)")
if let dictionary = child.value as? [String : AnyObject] {
let user = User()
user.setValuesForKeys(dictionary)
users.append(user)
}
}
self.userList = users
self.tableView.reloadData()
})
Simple question. Have you delegated your tableview?
class YourController: < other >, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() { //for example this function
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
}

Swift - table is empty after moving between controllers

I'm updating existing Objective-C app.
There is a structure:
AppDelegate
- creates mainBackgroundView and adding subview with UITabBarController
I have in one "Tab" HistoryViewController:
#objc class HistoryViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let historyTableViewController = HistoryTableViewController()
self.view.addSubview(historyTableViewController.view)
}
}
And HistoryTableViewController:
import UIKit
#objc class HistoryTableViewController: UITableViewController {
// Mark: properties
var historyCalls = [HistoryItem]()
// Mark: private methods
private func loadSimpleHistory() {
let hist1 = HistoryItem(personName: "Test", bottomLine: "text", date: "10:47")
let hist2 = HistoryItem(personName: "Test 2", bottomLine: "text", date: "10:47")
let hist3 = HistoryItem(personName: "Test 3", bottomLine: "text", date: "10:47")
historyCalls += [hist1, hist2, hist3]
}
override func viewDidLoad() {
super.viewDidLoad()
self.loadSimpleHistory()
self.tableView.register(UINib(nibName: "HistoryCallTableViewCell", bundle: nil), forCellReuseIdentifier: "HistoryCallTableViewCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return historyCalls.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "HistoryCallTableViewCell", for: indexPath) as? HistoryCallTableViewCell else {
fatalError("Coulnd't parse table cell!")
}
let historyItem = historyCalls[indexPath.row]
cell.personName.text = historyItem.personName
cell.bottomLine.text = historyItem.bottomLine
cell.date.text = historyItem.date
return cell
}
}
When I open the navigation tab with HistoryViewController for the first time, table appers with data. When I click into the table or switch navTab and then go back, table is not there anymore.
When I switch to another app and then go back, table is there again.
How to fix this?
Thank you
Call data method in viewwillappear and reload the table..
override func viewWillAppear() {
super.viewWillAppear()
self.loadSimpleHistory()
self.tableview.reloadData()
}

Swift- passing data from a multiple-section tableview to ViewController

I have a two-section tableview (see image below)
When I click row "A", another tableview shows up with letter "A"
When I click row "B", another tableview shows up with letter "B"
How can I pass the letter "C" to another tableview when I click row C ?
Here's my code in TableView:
import UIKit
class manhinh1: UITableViewController {
var UserDefault:NSUserDefaults!
var array:[[String]]!
override func viewDidLoad() {
super.viewDidLoad()
UserDefault = NSUserDefaults()
array = [["A","B"],["C","D","E"]]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return array.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
if section == 0 {
return array[0].count
}
if section == 1 {
return array[1].count
}
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
if indexPath.section == 0 {
cell.textLabel?.text = array[0][indexPath.row]
}
if indexPath.section == 1 {
cell.textLabel?.text = array[1][indexPath.row]
}
// Configure the cell...
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var row = self.tableView.indexPathForSelectedRow()!.row
UserDefault.setObject(array[0][row], forKey: "selected")
}
}
Here's the code in second view:
import UIKit
class ViewController: UIViewController {
var UserDefault:NSUserDefaults!
#IBOutlet weak var lbldata: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
UserDefault = NSUserDefaults()
// Do any additional setup after loading the view, typically from a }
lbldata.text = UserDefault.objectForKey("selected") as! String
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I did try a few code in prepareForSegue, but it didn't work. I hope you guys can show me a way. Thanks
You have to get the row and the section to access your multidimensional array. Then get the destination view controller of your segue and assign the corresponding value from the array to the UserDefault property:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var row = self.tableView.indexPathForSelectedRow()!.row
var section = self.tableView.indexPathForSelectedRow()!.section
var destinationViewController = segue.destinationViewController as! ViewController
destinationViewController.UserDefault.setObject(array[section][row], forKey: "selected")
}

How to get a UITableView method to run before another override method?

Below is my code. After testing the app for a bit I realized that the didSelectRowAtIndex is run AFTER prepareForSegue. How can I get didSelectRowAtIndex to run first.
If the answer involves threading, I have no idea how that works so please explain. Thank-you.
import UIKit
class AvailableShifts: UITableViewController {
var shiftData: NSMutableArray = NSMutableArray()
var shiftID: String!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
// self.refreshControl = UIRefreshControl()
//
// self.refreshControl?.addTarget(self, action: "refreshList", forControlEvents: .ValueChanged)
loadData()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return shiftData.count
}
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell {
let cell:AvailableShiftsCell = tableView!.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath!) as AvailableShiftsCell
let shift: PFObject = shiftData.objectAtIndex(indexPath!.row) as PFObject
cell.locationLabel.text = shift.objectForKey("Location") as String?
cell.shiftLabel.text = shift.objectForKey("Shift") as String?
cell.dateLabel.text = shift.objectForKey("Date") as String?
cell.id.text = shift.objectId
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let shift: PFObject = shiftData.objectAtIndex(indexPath.row) as PFObject
shiftID = shift.objectId
println(shiftID)
}
func loadData () {
var getShifts = PFQuery(className: "Shifts")
getShifts.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if (error == nil) {
self.shiftData.removeAllObjects()
for object in objects {
self.shiftData.addObject(object)
}
let array: NSArray = self.shiftData.reverseObjectEnumerator().allObjects
self.shiftData = array.mutableCopy() as NSMutableArray
self.tableView.reloadData()
}
}
}
#IBAction func refreshButtonPressed(sender: AnyObject) {
loadData()
}
// func refreshList() {
//
// loadData()
//
// self.refreshControl?.endRefreshing()
//
// }
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "details") {
var svc = segue.destinationViewController as ShiftOverview;
svc.shiftID = shiftID
println(shiftID)
}
}
}
There's no need to implement didSelectRowAtIndexPath at all for your application. If the segue is made from the cell, then the sender argument in prepareForSegue:sender: will be the cell. You can use the table view method indexPathForCell: to get the indexPath, and thus the PFObject you need.

delegate modal view swift

I have tried the other methods for delegation and protocols for passing data between modal views and the parent view button they aren't working for me. This is obviously because I am implementing them wrong.
What I have is a parent view controller which has a tableviewcell which in the right detail will tell you your selection from the modal view. The modal view is another table view which allows you to select a cell, which updates the right detail and dismisses the modal view. All is working except the actual data transfer.
Thanks in advance!! :)
Here is my code for the parent view controller:
class TableViewController: UITableViewController, UITextFieldDelegate {
//Properties
var delegate: transferData?
//Outlets
#IBOutlet var productLabel: UILabel!
#IBOutlet var rightDetail: UILabel!
override func viewWillAppear(animated: Bool) {
println(delegate?.productCarrier)
println(delegate?.priceCarrier)
if delegate?.productCarrier != "" {
rightDetail.text = delegate?.productCarrier
productLabel.text = delegate?.productCarrier
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 5
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return 1
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
The code for the model view controller and protocol is:
protocol transferData {
var priceCarrier: Double { get set }
var productCarrier: String { get set }
}
class ProductsDetailsViewController: UITableViewController, transferData {
//Properties
var priceCarrier = 00.00
var productCarrier = ""
//Outlets
//Actions
#IBAction func unwindToViewController(segue: UIStoryboardSegue) {
self.dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
populateDefaultCategories()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return Int(Category.allObjects().count)
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return (Category.allObjects()[UInt(section)] as Category).name
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return Int(objectsForSection(section).count)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:ProductListCell = tableView.dequeueReusableCellWithIdentifier("productCell", forIndexPath: indexPath) as ProductListCell
let queriedProductResult = objectForProductFromSection(indexPath.section, indexPath.row)
cell.name.text = queriedProductResult.name
cell.prices.text = "$\(queriedProductResult.price)"
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = self.tableView.indexPathForSelectedRow()!
let product = objectForProductFromSection(indexPath.section, indexPath.row)
let PVC: TableViewController = TableViewController()
println("didSelect")
productCarrier = product.name
priceCarrier = product.price
println(productCarrier)
println(priceCarrier)
self.dismissViewControllerAnimated(true, completion: nil)
}
I think for passing data, you should use segue like:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = self.tableView.indexPathForSelectedRow()!
let product = objectForProductFromSection(indexPath.section, indexPath.row)
println("didSelect")
productCarrier = product.name
priceCarrier = product.price
println(productCarrier)
println(priceCarrier)
self.performSegueWithIdentifier("displayYourTableViewControllerSegue", sender: self)
}
and then override the prepareForSegue function:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var controller = segue.destinationViewController as TableViewController
controller.rightDetail.text = "\(self.priceCarrier)"
controller.productLabel.text = self.productCarrier
}

Resources