在 cellforitem 中显示两种不同类型的单元格 swift

displaying two different types of cells in cellforitem swift

我有两个数组,一个包含字符串,一个包含自定义对象。

我分别创建了两个不同的单元格。我已将两个数组的内容添加到第三个通用数组 Any 中。我在 cellForItem.

中使用第三个数组 (combinedArray)
var customObjectArray: [customObject] = []
var stringArray = [String]()
var combinedArray = [Any]()

if combinedArray[indexPath.row] is CustomObject {


        cell1.LabelName.text = customObjectArray[indexPath.row].caption
        cell1.iconView.image = customObjectArray[indexPath.row].icon
        return cell1 
} else {

       let stringName = stringArray[indexPath.row]
       cell2.LabelName.setTitle(stringName for: UIControlState())
       return cell2
    }

假设 customObjectArray 有 13 个对象,stringObjectArray 有 17 个对象。我希望每个数组都有一个单独的计数器,以便正确填充它们。它现在的工作方式:

combinedArray 首先填充所有一种类型(即首先填充 13 个 customObjectArray),然后是第二个类型(即 17 个 stringObjects)。组合数组的顺序不一定很重要,因为我可能会在到达 cellforitem 之前的某个时候随机播放。因此,当 cellforItem 遍历前 13 个对象时,indexpath.row = 14,并且当它到达第二类对象时,它会跳过前 13 个对象并显示 stringObject 的第 14 个元素(很明显)。

我不知道如何从第二个数组的开头而不是 indexPath.row 的当前位置开始。

我可能完全偏离了这里的基础,可能应该使用两个部分或类似性质的东西,但我对 iOS 开发人员来说还比较陌生,因此欢迎任何指导。

始终只使用一个数组,其类型比 Any

更具体

例如,创建一个包含两种类型共有的所有属性和函数的协议

protocol CommonType {
   var labelName : String { get }
   // var ...
   // func 
}

并使类型采用协议。

然后声明具有该类型的单个数组,以便能够添加两种静态类型

var commonArray = [CommonType]()

cellForItem中通过条件向下转换类型确定单元格类型

let common = commonArray[indexPath.row]
if common is CustomObject {
   let cell = tableView.dequeueReusableCell(withIdentifier: "CustomObject", for: indexPath) as! CustomObjectCell
   cell.LabelName.text = common.labelName
   return cell
} else {
   let cell = tableView.dequeueReusableCell(withIdentifier: "Other", for: indexPath) as! OtherCell
   cell.LabelName.text = common.labelName
   return cell
}

indexPath 数学很麻烦而且容易出错。

另一种选择是将不同的数据类型包含在一个枚举中,然后将所有数据以您想要的任何顺序添加到组合数组中。

enum DataHolder {
    case stringType(String)
    case customType(CustomObject)
}

var combinedArray: [DataHolder]

这为您提供了单一的数据类型和区分单元格类型的方法。

cellForItem 内部对 combinedArray

执行切换
switch combinedArray[indexPath.row] {
    case .stringType(let stringValue):
        let cell = tableView.dequeueReusableCell(withIdentifier: "StringCell", for: indexPath) as! StringObjectCell
        cell.labelName.text = stringValue
    case .customType(let customData):
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomObjectCell
        cell.labelName.text = customData.caption
        cell.iconView.image = customData.icon

如果您想在 UITableView 中显示 2 种不同类型的数据,您可以简单地创建一个包装 enum,其案例将代表该类型。根据情况,您将始终知道如何配置单元。

示例: 假设您需要在 UITableView 中显示 Facebook 帖子,并且有 3 种类型的帖子:文本、图片和视频。您的 enum 想要这样:

enum Post {
  case text(String)
  case image(URL)
  case video(URL)
}

很简单吧? 您需要为每种类型的数据创建 UITableViewCell 个子类(或者单个并正确配置它,但出于多种原因我建议分开使用)。

现在您需要做的就是保留 Post 的数组并在您的 UITableViewDataSource 中构建您需要的单元格。

let post = self.posts[indexPath].row
switch post {
  case .text(let text):
    let cell = // dequeue proper cell for text
    // configure the cell
    cell.someLabel.text = text
    return cell
  case .image(let url):
    let cell = // dequeue proper cell for image
    // configure the cell
    cell.loadImage(url)
    return cell
  case .video(let url):
    let cell = // dequeue proper cell for video
    // configure the cell
    cell.videoView.contentURL = url
    return cell
}