Search code examples
iosiphoneuitableviewparse-platformtableview

TableView Parse Swift data not showing within the app


I just started coding and I search several posts, but I can't find why my data in the app is not showing up.

It's fetching my data, but I don't understand how I can add it to the tableView My first code for the "override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell" is still there, and please explain why it didn't work. Want to understand why it wasn't working.

class MasterTableViewController: PFQueryTableViewController, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate {

var noteObjects: NSMutableArray! = NSMutableArray()

@IBAction func logoutAction(sender: UIBarButtonItem) {
    PFUser.logOut()
    viewDidAppear(true)
}

// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
    super.init(style: style, className: className)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    
    // Configure the PFQueryTableView
    self.parseClassName = "Note"
    self.textKey = "title"
    self.pullToRefreshEnabled = true
    self.paginationEnabled = false
}

// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
    var query = PFQuery(className: "Note")
    query.orderByAscending("updatedAt")
    return query
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    
    if (PFUser.currentUser() == nil) {
        var logInViewController = PFLogInViewController()
        
        logInViewController.delegate = self
        
        var signUpViewController = PFSignUpViewController()
        
        signUpViewController.delegate = self
        
        logInViewController.signUpController = signUpViewController
        
        self.presentViewController(logInViewController, animated: true, completion: nil)
        
    }else {
        
        //self.fetchAllObjectsFromLocalDatastore()
        
        //self.fetchAllObjects()
    }
}

func fetchAllObjectsFromLocalDatastore() {
    
    var query: PFQuery = PFQuery(className: "Note")
    
    //query.cachePolicy = .CacheElseNetwork
    
    query.fromLocalDatastore()
    
    query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
    
    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]?, error: NSError?) -> Void in
        
        if (error == nil) {
            
            if let objects = objects as? [PFObject] {
                for object in objects {
                    println(object.objectId)
                }
            }
            
            var temp: PFObject = PFObject()
            
            self.noteObjects = temp.mutableCopy() as! NSMutableArray
            
            self.tableView.reloadData()
            
        }else {
            
            println(error!.userInfo)
        }
    }
}

func fetchAllObjects() {
    
    PFObject.unpinAllObjectsInBackgroundWithBlock(nil)
    
    var query: PFQuery = PFQuery(className: "Note")
    
    //query.cachePolicy = .CacheElseNetwork
    
    query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
    
    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]?, error: NSError?) -> Void in
        
        if (error == nil) {
            
            PFObject.pinAllInBackground(objects, block: nil)
            
            self.fetchAllObjectsFromLocalDatastore()
            
        }else {
            
            println(error!.userInfo)
        }
    }
}


// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 0
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section.
    return self.noteObjects.count
}

//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
    
    var cell = tableView.dequeueReusableCellWithIdentifier("cell") as! MasterTableViewCell!
    if cell == nil {
        cell = MasterTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
    }
    
    // Extract values from the PFObject to display in the table cell
    if let titleLabel = object?["title"] as? String {
        cell?.masterTitleLabel?.text = titleLabel
    }
    if let textView = object?["text"] as? String {
        cell?.masterTextLabel?.text = textView
    }
    
    return cell
}

//First try did find the code above afterwards
/*override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
    let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MasterTableViewCell

    // Configure the cell...
    
    var object: PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
    
    cell.masterTitleLabel?.text = object["title"] as? String
    cell.masterTextLabel?.text = object["text"] as? String
    
    return cell
}*/

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    
    self.performSegueWithIdentifier("editNote", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
    var upcoming: AddNoteTableViewController = segue.destinationViewController as! AddNoteTableViewController
    
    if (segue.identifier == "editNote") {
        
        let indexPath = self.tableView.indexPathForSelectedRow()!
        
        var object: PFObject = self.noteObjects.objectAtIndex(indexPath.row)as! PFObject
        
        upcoming.object = object;
        
        self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }
}


// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return NO 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, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        // Delete the row from the data source
        let objectToDelete = noteObjects?[indexPath.row] as! PFObject
        objectToDelete.deleteInBackgroundWithBlock {
            (success: Bool, error: NSError?) -> Void in
            if (success) {
                // Force a reload of the table - fetching fresh data from Parse platform
                self.fetchAllObjects()
            } else {
                // There was a problem, check error.description
            }
        }
    } 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
    }
}


//Signup and Login ViewController created by Parse
func logInViewController(logInController: PFLogInViewController, shouldBeginLogInWithUsername username: String, password: String) -> Bool {
    
    logInController.fields = (PFLogInFields.UsernameAndPassword
        | PFLogInFields.LogInButton
        | PFLogInFields.SignUpButton
        | PFLogInFields.PasswordForgotten)
    
    if (!username.isEmpty || !password.isEmpty) {
        return true
    }else  {
        return false
    }
}

func logInViewController(logInController: PFLogInViewController, didLogInUser user: PFUser) {
    self.dismissViewControllerAnimated(true, completion: nil)
    
}

func logInViewController(logInController: PFLogInViewController, didFailToLogInWithError error: NSError?) {
    println("Failed to log in...")
}

func signUpViewController(signUpController: PFSignUpViewController, shouldBeginSignUp info: [NSObject : AnyObject]) -> Bool {
    
    if let password = info["password"] as? String {
        
        return count(password.utf16) >= 8
        
    } else {
        return false
    }
}

func signUpViewController(signUpController: PFSignUpViewController, didSignUpUser user: PFUser) {
    self.dismissViewControllerAnimated(true, completion: nil)
}

func signUpViewController(signUpController: PFSignUpViewController, didFailToSignUpWithError error: NSError?) {
    println("Failed to sign up...")
}

func signUpViewControllerDidCancelSignUp(signUpController: PFSignUpViewController) {
    println("User dissmissed sign up.")
}
}

update: changing the numberOfSections didn't help

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

Solved

It's working now, changed this part of the code

func fetchAllObjectsFromLocalDatastore() {
    
    var query: PFQuery = PFQuery(className: "Note")
    
    //query.cachePolicy = .CacheElseNetwork
    
    query.fromLocalDatastore()
    
    query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
    
    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]?, error: NSError?) -> Void in
        
        if (error == nil) {
            
            if let objects = objects as? [PFObject] {
                for object in objects {
                    println(object.objectId)
                }
            }
            
            //var temp: PFObject = PFObject()
            
            //self.noteObjects = temp.mutableCopy() as! NSMutableArray
            
            //println(self.noteObjects)
            
            self.tableView.reloadData()
            
        }else {
            
            println(error!.userInfo)
        }
    }
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section.
    return objects!.count
}

Solution

  • @DenisE I had the same trouble and your solution of adding self.tableView.reloadData() fixed it. The reason we have to do this is I believe because view is already appeared and data was queried after that, so unless we reload that queried data in view it won't reflect in UI.