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

时间:2018-08-04 19:04:25

标签: swift uicollectionviewcell collectionview

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

我分别创建了两个不同的单元。我已将两个数组的内容添加到第三个通用数组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开发人员来说相对较新,因此可以接受任何指导。

3 个答案:

答案 0 :(得分:1)

始终仅使用一个类型比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数学麻烦且容易出错。

答案 1 :(得分:1)

另一种选择是将不同的数据类型包含在枚举中,然后将所有数据按您希望的顺序添加到组合数组中。

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

答案 2 :(得分:0)

如果要在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
}