Update Custom UITableViewCell UILabel after asynchronous Parse query - ios

Can't think of a good name for the question...if you can think of a better one, please feel free to edit it :)
I am building an iOS app using Swift and Parse.com.
In my app, I have a main PFQueryTableViewController which loads some data from my Parse cloud into some custom UITableViewCells.
One of the values that I want for a label on the cells takes a while for Parse to return and so I am getting it using findObjectsInBackgroundWithBlock().
In my cellForRowAtIndexPath when I'm loading my table, I have the following code:
// Set cells for each row of table
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
var cell: CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! CustomTableViewCell
// Get Course Object objectID to hand to getCourseGrade function
var anObjectID: String = object!.objectId!
cell.setCell(name: object!["objectName"] as! String, code: object!["objectCode"] as! String, grade: getObjectGrade(anObjectID))
return cell
}
In the code above, I am calling a function called getObjectGrade to pass a value across to my setCell() function which sets up the customTableViewCells as it builds the UITableView which runs as below (simplified):
func getObjectGrade(objectIdString: String) -> Float {
// Set a starting value of objectGrade
var objectGrade: Float = -1
//...I set up a PFQuery
query?.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
//...here I am retrive the value I need from Parse --> valueFromParse
objectGrade = valueFromParse
})
return objectGrade
}
NOW, I am VERY AWARE that this will NOT work...obviously the code does not wait for my findObjectsInBackgroundWithBlock() code to run and so returns the objectGrade before it has been updated.
MY QUESTION: How could I set the value of the label of my cell once the findObjectsInBackgroundWithBlock() code section DOES complete?

SOLVED! I moved the "getObjectGrade" function to my CustomTableViewCell file and called it from there. :) If anyone has this issue and needs help, just comment and i'll try :)

Related

Swift: Strange downcasting failure

I have a rather strange case of downcasting failure that I cannot understand.
I have almost identical code in two UITableViewControllers. ProjectTableViewController displays list of Project, and its datasource is [Project]. NewsfeedsTableViewController displays list of Newsfeed, but Newsfeed can contain different types of source data, including Project.
Depending on the type of the source data, each cell of NewsfeedsTableViewController is downcasted to appropriate subclass of UITableViewCell.
ProjectTableViewCell a subclass of UITableViewCell, and is used in both ProjectTableViewController and NewsfeedsTableViewController.
Now the interesting thing is, the code works without issue in ProjectTableViewController but crashes in NewsfeedsTableViewController, giving following error message:
Could not cast value of type 'UITableViewCell' (0x102e68128) to 'sample_app.ProjectTableViewCell' (0x1010ce6d0).
I have following codes in each class:
ProjectTableViewController.swift
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let project = projects[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("ProjectTableViewCell") as! ProjectTableViewCell
cell.projectTitle.text = project.title
cell.projectKeywords.text = project.keywords
return cell
}
NewsfeedsTableViewController.swift
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let newsfeed = self.newsfeeds[indexPath.row]
switch newsfeed.newsfeedableType {
case "Project":
let cell = tableView.dequeueReusableCellWithIdentifier("NewsfeedTableViewCell") as! ProjectTableViewCell
let source = newsfeed.newsfeedable as! Project
cell.projectTitle.text = source.title
cell.projectKeywords.text = source.keywords
return cell
default:
let cell = tableView.dequeueReusableCellWithIdentifier("NewsfeedTableViewCell")!
cell.textLabel!.text = newsfeed.newsfeedableType + String(newsfeed.id)
return cell
}
}
I would love to understand what's causing this issue.
The issue was solved by adding another prototype cell of ProjectTableViewCell to the NewsfeedsTableViewController, and using it to display Newsfeed with Project as source.
Which means I will have to add prototype cells for all the source data types, and then configure them on the storyboard. I'm not looking forward to doing that.
I thought I could duck-type through this all, but I guess Swift does not work like that.

Can't display custom cell with PFQueryTableViewController (Swift2)

Using parse.com v1.4 (installed with cocoa pods) with Swift 2 +
I've setup up my PFQueryTableViewController (ParseUI) with a custom cell. I believe everything is hooked up fine, however I can't get the cell to display the value from Parse.com even though I do receive it and can print it (I've debugged it).
I am dequeueing like this:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! OrderTableViewCell
// Extract values from the PFObject to display in the table cell
if let pfObject = object {
// prints expected value, e.g. 1, 2, 3
print(pfObject["table"])
// shows "Label" which is my label's default text on the SB!!
let table = pfObject["table"] as? String
cell.lblTable.text = table
}
return cell
}
The rest of my PFQueryTableViewController which seems to load data OK from Parse:
My custom cell OrderTableViewCell (with some label IBActions):
SB set-up:
And the result:
How can I get the label to display the actual text? What am I missing? I don't want to revert back to standard UITableView due to the additional features I get with Parse UI.
turns out it was as simple as changing
let table = pfObject["table"] as? String
to
let table = String(pfObject["table"])

Parse.com query.limit doesn't work in PFCollectionView

First, thanks for helping. I am writing an iOs application developed with Swift and i'm using Parse.com. In a class named liste_joueurs, there is around 15 rows. However, I just want to retrieve the first four results.
I read the docs and found the query.limit property. Unfortunately, when I run my code, in my collection, all the rows from my class appear (the query.limit doesn't work).
Does anyone have a solution ?
override func queryForCollection() -> PFQuery {
let query = PFQuery(className: "liste_joueurs")
query.limit = 4 // Useless
query.orderByAscending("nom")
return query
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFCollectionViewCell? {
println(object["nom"]?.count)
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("statsCell", forIndexPath: indexPath) as! StatsViewCell
// CELL'S TREATMENT
return cell
}
PS : When I used a constraint like this one :
query.whereKey("nom", hasPrefix: "ba")
The query "is filtered" and only rows beginning by "ba" appears in my collection...
With only this code I can say if you are using PFQueryCollectionViewController than make sure paginationEnabled = false, otherwise it will ignore. and if you are using objectsPerPage then it will override limit

Not populating UiTableView with Parse.com results in SWIFT

I am hoping someone can help, as I am trying to debug, but am going round in circles.
I have a table in Parse.com and can query and retrieve data successfully.
I did a test with a println and the correct values of the strings are displayed in the output.
What I was trying to do was put these values into a UITableView, but this has taken me down some pretty frustrating paths (I am still trying to learn this as best as I can and sometimes some concepts are hard to comprehend).
My last attempt (see code below) I thought by writing the values to a struct I could use this as I have done in the past, given that I can see the values I need to populate. I don't think this is the right way but I thought it should work.
My code when I put a breakpoint in doesn't get to even defining the tableview :(
I know I am missing something but maybe just need a fresh pair of eyes to help me see what I am missing.
Any help would be greatly appreciated:
#IBOutlet weak var navlabel: UILabel!
var TopicPassed:String!
var storedsentences=[getsentences]()
#IBOutlet weak var sentencetableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
navlabel.text = TopicPassed
var query = PFQuery(className:"TalkToMeSentences")
query.whereKey("Topic", equalTo:TopicPassed)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
// query successful - display number of rows found
println("Successfully retrieved \(objects.count) sentences")
// print sentences found
for object in objects {
let retrievedsentences = object["Sentence"] as NSString
self.storedsentences = [getsentences(parsesentence: "\(retrievedsentences)")]
println("\(retrievedsentences) ")
}
self.sentencetableview.reloadData()
} else {
// Log details of the failure
println("Error: \(error) \(error.userInfo!)")
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return storedsentences.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var sentence : getsentences
// Configure the cell...
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
cell.textLabel!.lineBreakMode = NSLineBreakMode.ByWordWrapping
sentence = storedsentences[indexPath.row]
cell.textLabel!.text = sentence.parsesentence
cell.textLabel?.numberOfLines = 0
return cell
}
Resolved it, I think.
My problem was I had not assigned outputs for the the datasource or the delegates.
Once I did I could get the table to populate.

(Swift) tableView application iOS fails because of "Bound value in a conditional binding must be of Optional type"

I am trying to create a database-based application for iOS and I am, more or less, forced to use Xcode 6.2 Beta 3, because I started the project with 6.2 and run iOS 8.2 on my testdevice. I have by the way figured out that the beta forces me to use the standard keypad, instead of decimal pad, otherwise the app stops working.
I canĀ“t figure out what is wrong. And when I try to comment the function out something is still wrong in this file. Are there any missing connections between the VC-swift-file, tableVC-swift-file and datamodel-file?
I changed the name of the entity list once, and then changed back, because of another error I had before. But after I did it seems like the debug area doesnt catch the data I try to save to the database either...
The error says "Bound value in a conditional binding must be of Optional type"
Here is the code that is marked red on the initial line:
if let ip = indexPath {
var data: NSManagedObject = tankningslista[ip.row] as NSManagedObject
cell.textLabel?.text = data.valueForKey("datum") as String
}
The whole function looks like this:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Configure the cell...
let CellID: NSString = "Cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID) as UITableViewCell
if let ip = indexPath {
var data: NSManagedObject = tankningslista[ip.row] as NSManagedObject
cell.textLabel?.text = data.valueForKey("datum") as String
}
return cell
}
I have followed this tutorial: https://www.youtube.com/watch?v=4ymz6i07DRM
try this way without using condition:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Configure the cell...
let CellID: NSString = "Cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID) as UITableViewCell
var data: NSManagedObject = tankningslista[indexPath.row] as NSManagedObject
cell.textLabel.text = data.valueForKey("datum") as? String
return cell
}

Resources