swift - 用不同的单元格重新加载 CollectionView
问题描述
我是 swift 的初学者,想创建我的第一个应用程序。在应用程序中,我使用 collectionViews,因为我遵循 Lets build that App on Youtube 的建议。
在我的应用程序中,我想要一个垂直的 collectionView。在这个 collectionView 中,我想要另一个包含 2 个不同单元格的 collectionView:1x TitleCell 和 ?x ContentCell。
对于这些单元格,发送一个 API 请求来设置它们的值。API调用完成后,我重新加载collectionView:
self.collectionView.reloadData()
不幸的是,当我重新加载数据时,我的 TitleCell 被 ContentCell 覆盖。正如我在有关 reloadData() 的 swift 文档中所读到的:当它被调用时,它会擦除每个单元格并将其替换为最后一个调用的单元格:在我的情况下是 ContentCell。
因此我的问题是,有没有办法以不被覆盖的方式重新加载 TitleCell 和 ContentCell ?
还有:用 2 个不同的单元格制作 collectionView 是不是一种不好的做法?
这是我的代码:
接口:
class ApiService: NSObject {
static let sharedInstance = ApiService()
var contentBaseUrl = "netAddress"
func fetchContent(from url: String, completion: @escaping ([ContentModel]) -> ()) {
fetchFeedForUrlString(urlString: "\(contentBaseUrl)/"folder"/\(url)", completion: completion)
}
func fetchFeedForUrlString<T: Decodable>(urlString: String, completion: @escaping (T) -> ()) {
let url = URL(string: urlString)
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard let data = data else {
return
}
do {
let json = try JSONDecoder().decode(T.self, from: data)
DispatchQueue.main.async {
completion(json)
}
} catch let jsonError {
print(jsonError)
}
}
task.resume()
}
}
调用 api 的 CollectionView:
class VHomeCell: BaseCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var firstCell = true
var content: [ContentModel]?
override func setupViews() {
super.setupViews()
fetchVideos()
collectionView.register(HomeContentCell.self, forCellWithReuseIdentifier: "ContentCellID")
collectionView.register(LeagueCell.self, forCellWithReuseIdentifier: "TitleCellID")
}
//Method that causes the "error"
func fetchMatches() {
ApiService.sharedInstance.fetchData(from: "ApiNetworkAddress", completion: { (content: [ContentModel]) in
self.content = content
self.collectionView.reloadData()
})
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return content?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if firstCell {
firstCell = false
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TitleCellID", for: indexPath) as! TitleCell
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ContentCellID", for: indexPath) as! ContentCell
cell.match = matches?[indexPath.item]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: frame.width, height: 50)
}
ContentCell 和 TitleCell 只是 2 个 UICollectionView 单元,其中包含不同的内容:
class TitleCell: BaseCell {
var content: ContentModel? {
didSet {
title.text = content.titleText
}
}
}
class ContentCell: BaseCell {
var content: ContentModel? {
didSet {
content.Text = content.text
}
}
}
这是使用的 BaseCell:
class BaseCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
func setupViews() {
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我知道我的代码需要大量的清理工作。因此,如果有人也能指出我可以如何清理我的代码或使其更有效率,我会很高兴。
解决方案
您不应该使用此firstCell
属性来确定在您的cellForItemAt
方法中配置哪个单元格。相反,您应该使用indexPath
传递给方法的参数来确定是否正在为第一个单元格调用该方法。您可以通过检查indexPath
's来做到这一点item
(您可以忽略indexPath
's section
,因为您的收藏视图中似乎只有一个部分)。
因此,完全删除该firstCell
属性。然后只需替换此if
条件:
if firstCell {
和:
if indexPath.item == 0 {
要回答您的另一个问题:不,每个集合视图有多个单元格类型并不是一个坏习惯。
推荐阅读
- php - 为什么没有将表单提交添加到我的 CSV 文件中?
- linux - git CRLF - Windows 和 Linux 问题
- css - 覆盖材质背景颜色 css
- javascript - 提示计算方程在第一个输出上工作,但在第二个输出上用 number() 返回 NaN
- angular - 自定义验证指令Angular 6模板驱动表单的“无提供者”?
- javascript - 页面刷新Vue.js和axios后的空数组
- azure-storage - Azure 存储 CloudFile 自定义元数据 API,如 Azure 存储资源管理器
- sass - 为什么我们使用 #{} 进行插值?我们不能只使用 scss 变量吗?
- matlab - 为什么 GPU 上的隐式扩展并不总是更快?
- oracle - OracleDataReader GetValue 抛出 InvalidOperationException