I am using includeKey to load multiple values from an array column in my PFObject. When I navigate to the tableView, however, the tableView only loads a single row
This is because the Parse cellForRowAtIndexPath method is only called once (when it should be called for the amount of values in the "following" array)
Here's my implementation
override func queryForTable() -> PFQuery {
let query = PFQuery(className: "Followers")
query.whereKey("username", equalTo: username)
query.includeKey("following")
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
let cell = tableView.dequeueReusableCellWithIdentifier(identifier) as! AccountQueryCell
let followerObject = object as! PFFollowers
cell.usernameLabel.text = followerObject.getFollowing()[indexPath.row]
cell.profileImage.username = followerObject.getFollowing()[indexPath.row]
return cell
}
As you can see, I return a query that includes the "following" array.
My Parse "Followers" class contains the following custom columns: "following" (Array) and "username" (String)
Could someone explain to me why my query isn't calling cellForRowAtIndexPath for every value in the following array?
I think the issue is that you are querying for all Followers objects which match a single username. Based on the description of your data model, this will result with only one object being found.
PFQueryTableViewController automatically sets the table view's data source according to the results of your query. In other words, the table view is being set to only create one cell to correspond to the one result from the query.
Related
The title might seem a bit vague or confusing because I don't know how to explain my issue in one line.
I have a tableview with ~ 500 cells where the details are filled with an API. The tableview has search / filter function based on the name.
For example , "ABCD" is on cell 456 and if I search ABCD, the tableview will refresh and put ABCD on cell 0.
let searchtextupper = searchText.uppercased()
searchActive = true
filterdata = self.name.filter { $0.contains("\(searchtextupper)")
Table.reloadData()
}
All this part is correct, but I want to get the indexPath of ABCD before the tableview is reloaded. I want to know that "ABCD" was on cell 456 before the tableview reloads and puts "ABCD" cell on cell 0.
How do I get that indexPath?
Answer,incase someone else needs it :
By using #Abhisheks answer.
I declared a simple int array on the class
var arrayofindices = [Int]()
then added it in the search/filter function
let indexArray = name.indices.filter { name[$0].localizedCaseInsensitiveContains(searchtextupper) }
arrayofindices = indexArray
and on didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var newindex = arrayofindices[indexPath.row]
searchmember.email = self.email[newindex]
}
Here searchmember is a struct and email is a variable in it. The self.email is a locally declared array to store email IDs which are received from API,having the entire list of emails before the filtering.
You can get index of filter position using this code. But first i think your name array might contain same name so in that case you need all the index for that name right?
For that use this code -
let indexArray = name.indices.filter { name[$0].localizedCaseInsensitiveContains(searchtextupper) }
Here in indexArray you will get all the index for such name.
And if you sure your name array will not contain duplicate names then -
let index = name.firstIndex{$0 === searchtextupper}
Hope this helps. Happy Coding
How do you sort table view cells based on the value in the detail text label? I have names and scores in Firebase that I'm pulling out and want to show in order of the highest to lowest score.
Currently, I'm retrieving the Firebase names and values, but they are just displayed by alphabetical order of the names in the main text field. I've tried sorting by the score values with {$0.scoreTotal > $1.scoreTotal} and ordering the Firebase data with queryOrdered(byChild: "scoreTotal"), but neither seems to work.
Here's the table view section of code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellMale", for: indexPath as IndexPath)
let comp = comps[indexPath.row]
self.comps.sorted(by: {$0.scoreTotal > $1.scoreTotal})
let dbRef1 = FIRDatabase.database().reference().child("Live Scoring Male/\(String(describing: comp.name!))/scoreTotal")
dbRef1.queryOrdered(byChild: "scoreTotal").observe(FIRDataEventType.value, with: { (snapshot) in
let scoreTotal = snapshot.value as! Double
cell.detailTextLabel?.text = String(scoreTotal)
})
cell.textLabel?.text = comp.name
return cell
}
First thing is never call any services into cellForRowAtIndex and call it when it needed like while we load view use viewDidLoad() method for loading any data into that Controller.
so call above method into viewDidLoad and regarding sorting your data
use FireBase sorting like below:
let ref = FIRDatabase.database().reference(fromURL: <FIREBASE_URL>).child("topics")
let query = ref.queryOrdered(byChild: "scores")
query.observe(.value, with: { (snapshot) in
for childSnapshot in snapshot.children {
print(childSnapshot)
}
})
catch this into Local Array or Dictionary and use it in your TableView with reloadData() method.
say me, please, how better compare two same (label has name "labelNumber") labels from different rows in Tableview
For example: I know, that in row №0 label is "06" (Int) and in next cell (row №1) this label is "07". So, "07" > "06". How compare it with swift language?
Thanks!
The wrong way
As stated by #vadian, you should NOT use the UI you populated to perform calculations on data.
However this is the code to compare the values inside 2 UITableViewCell(s)
class Controller: UITableViewController {
func equals(indexA: NSIndexPath, indexB: NSIndexPath) -> Bool? {
guard let
cellA = tableView.cellForRowAtIndexPath(indexA),
cellB = tableView.cellForRowAtIndexPath(indexB) else { return nil }
return cellA.textLabel?.text == cellB.textLabel?.text
}
}
The right way
Think about how you are populating the cells. I imagine you are using some Model Value. So just compare the Model Values you are using to populate the cells.
Probably something like this
class Controller: UITableViewController {
var data: [Int] = [] // ....
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCellWithIdentifier("YourCellID") else { fatalError("No cell found with this id: 'YourCellID'")}
cell.textLabel?.text = String(data[indexPath.row])
return cell
}
func equals(indexA: NSIndexPath, indexB: NSIndexPath) -> Bool? {
return data[indexA.row] == data[indexB.row]
}
}
Compare the values stored within your data array:
if dataArray[0].myIntegerValue > dataArray[1].myIntegerValue {
// Do your stuff
}
Edit: this assumes your data is stored as objects with that Int as an attribute.
As the others have said, don't do that. In the MVC design pattern, labels are views. They are for displaying data, not storing it.
Trying to read values from table view labels is especially bad, because as the table view scrolls, the cells that go off-screen will be recycled and the values in their views will be discarded. You need to save your data to a model object. (An array works just fine to save table view data, or an array of arrays for a sectioned table view.)
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
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 :)