Swift:UICollectionViewCell只获取一次数据

时间:2020-05-17 04:00:14

标签: ios swift

我有一个水平滚动UICollectionView,每个collectionViewCell包含一个tableView,其中显示了post个对象的提要。我只想为每个collectionViewCell获取一次数据。

我当前的实现是在collectionViewCell出队时获取数据,即,当用户在collectionView上左右滑动时,单元有时会重新加载并获取数据,从而中断用户体验。

到目前为止的代码:

//At ViewController
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FeedCell
    cell.topic = topics[indexPath.item]
    return cell
}

//At FeedCell, the custom collectionViewCell
class FeedCell: UICollectionViewCell {

    lazy var tableView: UITableView = {
        let tv = UITableView(frame: .zero, style: .plain)
        tv.delegate = self
        tv.dataSource = self
        //Setup tableView work
        return tv
    }()

    var topic: Topic? {
        didSet {
             if let _ = topic {
                 getData()
             }
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        //Setup views work
    }

这是我的一些其他尝试:

尝试1 ,将getData()移至init(frame: CGRect),但由于尚未设置getData,因此未调用topic。< / p>

尝试2 ,将getData()移至layoutSubviews(),如下所示:

override func layoutSubviews() {
    if let _ = topic {
        getData()
    }

    super.layoutSubviews()

}

但这会递归调用getData()

更新getData()

的代码
var posts = [Post]()
fileprivate func getData() {
    getDataFromApi { (posts, err) in
        if let err = err {
           print(err)
        }

        if let posts = posts {
            DispatchQueue.main.async {
                if posts.count != 0 {
                    self.posts += posts
                    self.tableView.reloadData()
                }
            }        
        }
    }
}

2 个答案:

答案 0 :(得分:0)

如果您要在所有应用程序打开时都寻求性能,最好是在首次加载CoreData或诸如Parse Server或Firebase上的本地数据存储之类的数据后,将该数据与CoreData缓存到设备上

查询看起来像这样

->检查CoreData中所需的对象

->如果找到的对象几乎立即显示在集合单元的表格视图中

->如果没有对象从数据库加载到表视图中显示

->下次将加载的数据保存到CoreData中

CoreData Swift: How to save and load data?

如果您每次访问视图控制器时都希望提高性能,那么我会将数据存储到vc加载时的嵌套数组中

var tablesData = [[Object]]()

在前进的道路上,您可以在每次加载单元格后将它们设置为这样

tablesData[collectioncellindex] = tableobjects

然后,您可以在收集单元格上的每个tableView的后面访问类似的每个对象

let tableobject = tablesData[collectioncellindex][tableviewrow]

以第一个索引为收集单元(包含所有表数据),以第二个索引为表视图单元(具有一个表单元的数据)

您甚至还可以最初将所有数据加载到嵌套数组中,这样就不必在两次滑动之间加载数据-我想这取决于您需要加载多少数据以及哪种数据,但是如果不需要的话太长的时间可能是您更好的选择

希望这会有所帮助!

答案 1 :(得分:0)

在后台线程上调用getData()以便在下载数据时不阻塞主线程。 .userInteractive和.userInitiated都是高优先级后台线程。如果您希望下载文件简短快捷,请使用前一个,否则请使用后一个。

var topic: Topic? {
    didSet {
         if let _ = topic {
             DispatchQueue.global(qos: .userInitiated) {
                 self.getData()
             }
         }
    }
}

您可以通过添加activityIndi​​cator来改善用户体验,并在需要时使用缓存。缓存可以帮助您暂时保留数据,这样,当用户需要再次访问数据时,您不必重新下载数据。