CollectionViewController.reloadData()与来自Parse Server的数据

我已经search了网页,所有声称要解决的类似问题都是针对Objective-C的,或者他们现在没有工作。 有人有一个真实的例子与真实的数据,例如从服务器?

我正在创build一个parsing应用程序,我卡在self.collectionView.reloadData() 。 我可以看到我的数据源正在被来自服务器的数据填充。 在运行findObjectsInBackground(...) ,我可以看到numberOfSections(collectionView)的对象数是正确的,但是collectionView(_:cellForItemAt:)始终显示从Parse服务器返回的对象的索引永远不可用。

我自己创build的对象(如样本)工作正常。 这些对象可以很好地从服务器中获取,并放入我的本地数据存储中,在数据库读取操作完成后我可以看到它们。

我已经尝试过DispatchQueueOperationQueue.main.addOperationviewWillAppearviewDidLayoutSubviewsself.collectionViewLayout.invalidateLayout()viewDidAppearself.collectionView?.reloadItems(at:(self.collectionView?.indexPathsForVisibleItems)!)等等。

我也使用了Kyle Andrews的“Custom CollectionView Layouts: 在Swift中构build多方向UICollectionView ”教程。

这是collectionVieController类的完整代码。

 import UIKit import Parse private let reuseIdentifier = "Cell" /// This class will act as both the data source and delegate since UICollectionViewController conforms to both of our desired protocols: UICollectionViewDataSource and UICollectionViewDelegate. The data source will act as a vendor providing views and information, while the delegate handles managing selections and performing actions within the collection. class PaymentStatusCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout { //var users = Set<String>() var users:[String] = ["Name", "Andrew", "Peter", "Paul","Mark"] var payments:[String] = ["Payment", "100", "500", "200", "50"] fileprivate let concurrentPhotoQueue = DispatchQueue( label: "com.raywenderlich.GooglyPuff.photoQueue", attributes: .concurrent) let queue = DispatchQueue(label: "com.appcoda.myqueue") let queue2 = DispatchQueue.global() let button = UIButton() var usersPayments:[String:[String]] = ["Name":["Amount"]] //this object expects one entry per user. var usersTotalPayments:[String:String] = ["Name":"Total"] //var usersTotalPayments = [String:[String]]() //var usersTotalPayments = Dictionary<String, Array<String>>() @IBOutlet var paymentStatusCollectionView: UICollectionView! override func viewDidLoad() { super.viewDidLoad() // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Register cell classes // Do any additional setup after loading the view. usersTotalPayments["BB"] = "10000" usersTotalPayments["AA"] = "1000" //self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) //self.collectionView?.register(PaymentStatusCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) _ = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(PaymentStatusCollectionViewController.reloadData), userInfo: nil, repeats: false) //button.setTitle("Shoudl This Force..", for: []) //self.view.addSubview(button) } func reloadData() { DispatchQueue.main.async { [unowned self] in print(#function, "========================================") self.collectionView?.reloadData() } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(true) //print(#function, " :", usersTotalPayments.keys.count) //self.collectionView?.reloadData() //self.collectionView!.reloadItems(at: <#[IndexPath]#>) self.collectionView?.reloadData() //self.collectionView?.reloadInputViews() //self.collectionViewLayout.invalidateLayout() print(#function, " :", self.usersTotalPayments.keys.count) self.collectionView?.reloadItems(at:(self.collectionView?.indexPathsForVisibleItems)!) } // override func viewDidLayoutSubviews() { // super.viewDidLayoutSubviews() // //print(#function, " :", usersTotalPayments.keys.count) // self.collectionViewLayout.invalidateLayout() // } // override func viewWillAppear(_ animated: Bool) { // super.viewWillAppear(true) // getPaymentDetails() // } func getPaymentDetails() { //self.paymentStatusCollectionView.reloadData() // Do any additional setup after loading the view. let paymentsQuery = Payments.query() paymentsQuery?.findObjectsInBackground(block: { (objects, error) in if let objects = objects { // print(objects.count) if objects.count == 0 { // Utils.stopIndicator(activityIndicator: activityIndicator) Utils.createAlert(self, title: "No Payment has been made yet", message: "Please Encourage USers to make some Payments", buttonTitle: "Ok") // TODO:- i think here, we should go back to our homeScreen or to a list of possible friends... }else { //print(#function, " no. of objects :", objects.count) for paymentsObject in objects { let user = paymentsObject[Utils.name] as! String let amount = paymentsObject[Utils.amount] as! String self.usersTotalPayments[user] = amount self.users.append(user) self.payments.append(amount) //print(self.usersTotalPayments[user]!) //print(#function, " A ---- USER :", user) //if self.usersTotalPayments[user] == nil { // //print(#function, " B ---- 0") // self.usersTotalPayments[user] = [amount] // print(self.usersTotalPayments[user]!) //}else { // //print(#function, " C ---- Other") // self.usersTotalPayments[user]?.append(amount) // print(self.usersTotalPayments[user]!) //} } self.collectionView?.reloadData() print("Done Reloading with COUNT: ", self.usersTotalPayments.keys.count) }else if error != nil { print(error!) }else { print("Unknown Error") } }) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: UICollectionViewDataSource override func numberOfSections(in collectionView: UICollectionView) -> Int { // #warning Incomplete implementation, return the number of sections print(#function, " :", usersTotalPayments.keys.count) // guard let coumt = usersTotalPayments.keys!.count else { // return 0 // } //if usersTotalPayments.keys.count == 1 { // return 1 //} else { return users.count //} } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: 300, height:30) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { // #warning Incomplete implementation, return the number of items return 2 } // the function belo mde things worse // override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { // print(#function, " :", usersTotalPayments.keys.count) // collectionView.reloadData() // } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PaymentStatusCollectionViewCell print(#function, " :", indexPath) // Configure the cell cell.label.text = "Sec " + indexPath.section.description + "/Item " + indexPath.item.description cell.backgroundColor = (indexPath.item % 2 == 0) ? UIColor.yellow : UIColor.lightGray //let key = usersTotalPayments. if indexPath.item == 0 { //item0 represents the object in column 0. the section is the index for row cell.label.text = users[indexPath.section] }else if indexPath.item == 1{ cell.label.text = payments[indexPath.section] } return cell } override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { //print("selected \(indexPath)") } func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { // if isLandscape { // return CGSize(width: 200, height:30) // } // else { // return CGSize(width: 200, height:30) // } return CGSize(width: 200, height:30) } // // func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { // print(#function) // return self.view.frame.size // } // func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{ // //return CGSize(width: collectionView.bounds.width, height: collectionView.bounds.height) // return CGSize(width: 200, height:30) // } // // func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat{ // return 2 // } // // func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets{ // return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // } // // // // MARK: UICollectionViewDelegateFlowLayout // func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { // return 4.0 // } // }