如何跟踪数组中的更改和collectionview.reloaddata()

时间:2017-01-02 02:16:32

标签: swift swift3

我在我的collectionview中重新加载数据时遇到了问题。我有一个填充collectionview的数组。但是每当我向数组中添加更多项目时,除非我重新加载数据(),否则它不会显示。每当它看到数组中的更改时,无论是删除还是添加新元素,都可以使用collectionview reloaddata的最佳方法是什么?提前致谢!编辑:添加代码。

CheckoutController:UICollectionViewCell,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {

var inventoryTabController: InventoryTabController?

override init(frame: CGRect){
    super.init(frame: frame)
    setupViews()

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


func loadItems() -> [Item]? {
    return NSKeyedUnarchiver.unarchiveObject(withFile: Item.ArchiveURL.path) as? [Item]
}

func saveItems() {
    let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(checkout, toFile: Item.ArchiveURL.path)
    if !isSuccessfulSave {
        print("Failed to save items...")
    }
}

func addItem(item: Item) {
    items.append(item)
    collectionView.reloadData()
}

func editItem(item: Item, index: Int) {
    items[index] = item
    collectionView.reloadData()
}

func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    // Identify which segue is occuring.
    if segue.identifier == "ShowDetail" {
        let itemDetailViewController = segue.destination as! AddItemController

        // Get the cell that generated this segue.
        if let selectedItemCell = sender as? InventoryCell {
            let indexPath = collectionView.indexPath(for: selectedItemCell)!
            let selectedItem = items[indexPath.row]
            itemDetailViewController.item = selectedItem
        }
    }
    else if segue.identifier == "AddItem" {
        print("Adding new meal.")
    }
}

lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)

    cv.dataSource = self
    cv.delegate = self

    cv.backgroundColor = UIColor.rgb(r: 247, g: 247, b: 247)
    return cv
}()

let cellId = "cellId"
let paynow = "paynow"
func setupViews() {
    backgroundColor = .brown

    addSubview(collectionView)

    addConstraintsWithFormat("H:|[v0]|", views: collectionView)
    addConstraintsWithFormat("V:|[v0]|", views: collectionView)
    collectionView.indicatorStyle = UIScrollViewIndicatorStyle.white

    collectionView.register(PayNowCell.self, forCellWithReuseIdentifier: paynow)

    collectionView.register(CheckoutCell.self, forCellWithReuseIdentifier: cellId)
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return checkout.count //init number of cells
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    if indexPath.item == 0 {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paynow", for: indexPath) as! PayNowCell //init cells
    return cell
    }else{
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CheckoutCell //init cells
    print("Printing this \(checkout.count)")
    cell.item = checkout[indexPath.item]
    return cell
    }

}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    //let item = items[indexPath.item]
    //inventoryController?.showItemDetailForItem(item: item, index: indexPath.item)
    print("selected")
    print(indexPath.item)
    collectionView.reloadData()
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    if indexPath.item == 0 {
        return CGSize(width:frame.width, height: 100) //each cell dimensions
    }else{
        return CGSize(width:frame.width, height: 150) //each cell dimensions
    }
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

}

1 个答案:

答案 0 :(得分:3)

有很多方法可以做到这一点,但没有看到任何代码,我不能特别推荐一种特定的方法。最通用的是在您的阵列上设置didSet侦听器,并在更改时调用collectionView.reloadData()

 var dataArr = [1, 2, 3, 4] {
       didSet {
         //collectionView.reloadData()
         print("Changed from \(oldValue) to \(dataArr)")
       }  
}

dataArr.append(5)
//prints - Changed from [1, 2, 3, 4] to [1, 2, 3, 4, 5]
dataArr.removeFirst()
//prints - Changed from [1, 2, 3, 4, 5] to [2, 3, 4, 5]

根据有关全局变量的评论

编辑以下内容

你应该真的试图远离全局变量。由于您坚持列表,您可以在必要时检索它。我不打算详细介绍,但是有很多关于其原因的东西。现在我提到我会继续为你提供处理这种情况的方法。

当数组值更改时,您可以使用NotificationCenter发布应用程序范围的通知。然后在您希望的任何viewController中订阅通知。

extension Notification.Name {
    static let arrayValueChanged = Notification.Name("arrayValueChanged")
}

var dataArr = [1, 2, 3, 4] {
    didSet {
        NotificationCenter.default.post(name: .arrayValueChanged, object: nil)
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(forName: .arrayValueChanged, object: nil, queue: OperationQueue.main) { [weak self] (notif) in
            self?.collectionView.reloadData()
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}