CollectionViewController.reloadData() with data fr

2019-08-20 17:20发布

问题:

I have searched the web and all the similar questions that have claimed to be solved have been either for Objective-C or they are not working right now. Does someone have a real-life example with real data, for example from a server?

I am creating a Parse app and I'm stuck at self.collectionView.reloadData(). I can see my data source is being populated with data from the server. after running findObjectsInBackground(...), I can see that the number of objects is correct in numberOfSections(collectionView) but collectionView(_:cellForItemAt:) always shows that the indices for the objects returned from the Parse server are never available.

Objects I create on my own (like samples) are working fine. The objects are fetched nicely from the server and put in my local datastore and I can see them after the database fetch operation is complete.

I have already tried DispatchQueue, OperationQueue.main.addOperation, viewWillAppear, viewDidLayoutSubviews, self.collectionViewLayout.invalidateLayout(), viewDidAppear, self.collectionView?.reloadItems(at:(self.collectionView?.indexPathsForVisibleItems)!) and others.

I have also used the Kyle Andrews' tutorial on Custom CollectionView Layouts: Building a Multi-Directional UICollectionView in Swift.

This is the entire code for the collectionVieController class.

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
    //    }
    //
}