I am using CloudKit to store a few arrays, then use the arrays to fill a table. I am reloading the table, but it will not show any data. It should be connected to iCloud because I am still able to add to the database.
Code is shown below:
import UIKit
import CloudKit
var selectedCellName = ""
class explore: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet var tableView: UITableView!
var groupNames = [String]()
var Group = [CKRecord]()
override func viewDidLoad() {
super.viewDidLoad()
loadGroups()
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return groupNames.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "exploreCell")! as UITableViewCell
// let nameCell = leaderboardInfo[indexPath.row].object(forKey: "Name") as! String
// let usernameCell = leaderboardInfo[indexPath.row].object(forKey: "Username") as! String
//let pointsCell = leaderboardInfo[indexPath.row].object(forKey: "Points") as! String
var nameCellLbl = cell.viewWithTag(100) as! UILabel
nameCellLbl.text = groupNames[indexPath.row]
return cell
}
}
Here is the loadGroups()
function which is used to query the database:
func loadGroups(){
print("should go")
// let pred = NSPredicate(format: "Username = %@", usernameText)
let pred = NSPredicate(value: true)
let query = CKQuery(recordType: "Group", predicate: pred)
let operation = CKQueryOperation(query: query)
//operation.resultsLimit = CKQueryOperationMaximumResults
operation.qualityOfService = .default
operation.recordFetchedBlock = { (record: CKRecord!) in
if record != nil{
// need self in front?
groupNames.append(record.object(forKey: "groupName") as! String)
//self.tableView.reloadData()
//print(self.groupNames.count)
}
}
database.add(operation)
//self.tableView.reloadData()
// print(leaderboardInfo.count)
}
This used to work, and if I made changes I made them months ago so I can't remember. Anyway this is the problem in all of my files where I query the database, but the table won't load it.
You're reloading the table view long before you actually query the data.
Remove the call to reloadData
in viewDidLoad
.
In loadGroups
you need to setup a query completion handler. You need to deal with the possibility that the query completion hander will indicate that there is more data to load.
You should build a new array from the queried data. Don't update groupNames
until you have all of the data. Then, on the main queue, update groupNames
with the queried results and then reload the table view.
An even better solution is to add a completion handler to your loadGroups
method. Then instead of loadGroups
directly updating groupNames
and reloading the table view, it simply passes back a new array with all of the query data. Then the caller can update the groupNames
and reload the table view it the completion block it passes to the call to loadGroups
.
func loadGroups(completion: ((_ groups: [String]) -> Void)) {
var names = [String]()
// setup operation
...
operation.recordFetchedBlock = { (record: CKRecord!) in
if record != nil {
names.append(record.object(forKey: "groupName") as! String)
}
}
operation.queryCompletionBlock = { (cursor, error) in {
// properly handle cursor and error
completion(names)
}
}
Then this can be called from your view controller as:
loadGroups() { (names) in
DispatchQueue.main.async {
groupNames = names
tableView.reloadData()
}
}
The above is a rough outline. This is not meant to be production ready.