简体   繁体   English

如何使用if语句将变量类型设置为自定义tableCell的特定类型?

[英]How can I use an if statement to set a type of variable to a specific type of custom tableCell?

I have three different types of custom UITableCells. 我有三种不同类型的自定义UITableCells。 I have an if statement that sets them up: 我有一个if语句来设置它们:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {                
    if somePosts[indexPath.row].typeOfPost == .linkPost {
        let cell: LinkTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell

    } else if somePosts[indexPath.row].typeOfPost == .picturePost {
        let cell: PictureTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell

    } else if somePosts[indexPath.row].typeOfPost == .textPost {
        let cell: TextTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell


    } else {
        print("Type of post is not link, picture, or text")
    }
}

Each of the custom cells has similar labels such as title and time. 每个自定义单元格都有类似的标签,例如标题和时间。 I would like to set these labels using the same line of code, such as: 我想使用同一行代码来设置这些标签,例如:

cell.titleLabel.text = "Some title here"

However, in this example, I get an error saying I am using an unresolved identifier "cell," obviously because my variables are being declared non-globally. 但是,在此示例中,我收到一条错误消息,指出我使用的是未解析的标识符“单元格”,这显然是因为我的变量是非全局声明的。 Is there a way around this since swift is strongly typed? 由于swift是强类型的,是否有办法解决? Thanks! 谢谢!

Make a protocol that your TableViewCell classes extend, and store cell as a variable of that type. 制定一个协议,以供TableViewCell类扩展,并将cell存储为该类型的变量。

protocol MyTableViewCell {
    var titleLabel: UILabel { get }
    // ...
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let identifier: String

    switch somePosts[indexPath.row].typeOfPost {
        case .linkPost: identifier = "linkTableViewCell"
        case .picturePost: identifier = "pictureTableViewCell"
        case .textPost: identifier = "textTableViewCell"
        default: fatalError("Type of post is not link, picture, or text")
    }

    guard let cell = self.tableView.dequeueReusableCell(withIdentifier: identifier) as? MyTableViewCell else {
        fatalError("Cell isn't castable to MyTableViewCell")
    }

    cell.titleLabel.text = "Some title here" 
    // ...
}

You have three basic solutions. 您有三个基本解决方案。

  1. Repeat cell.text = ... inside each block. 在每个块内重复cell.text = ... But this isn't what you really want as stated in your question. 但是,这并不是您所提问题中真正想要的。
  2. Have your three custom cell classes all extend a common base class. 让三个自定义单元格类都扩展一个公共基类。 Have this base class define any common properties. 让该基类定义任何公共属性。
  3. Define a protocol with the common properties and have each of your custom cell classes conform to the protocol. 定义具有公共属性的协议,并使每个自定义单元格类均符合该协议。

For options 2 and 3 you would declare a variable of the base/protocol type before the first if statement. 对于选项2和3,您将在第一个if语句之前声明基本/协议类型的变量。 Then after the whole if/else block, you can assign any of the common properties. 然后,在整个if/else块之后,可以分配任何公共属性。

If you need to update any cell type specific properties, you can do that inside the appropriate block as well. 如果需要更新任何特定于单元格类型的属性,则也可以在适当的块内执行此操作。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell: BaseTableViewCell?
    if somePosts[indexPath.row].typeOfPost == .linkPost {
        cell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell
    } else if somePosts[indexPath.row].typeOfPost == .picturePost {
        cell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell
    } else if somePosts[indexPath.row].typeOfPost == .textPost {
        cell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell
    } else {
        print("Type of post is not link, picture, or text")
    }

    if let cell = cell {
        cell.commonProperty = ...

        return cell
    } else {
        return nil // this shouldn't happen but if it does, you have a bug to fix
    }
}

If the subclasses each have their own titleLabel property, you will need to make them all conform to a protocol. 如果每个子类都有自己的titleLabel属性,则需要使它们全部符合协议。 Let's call it ConfigurableCell . 我们称之为ConfigurableCell

protocol ConfigurableCell {
    var titleLabel: UILabel { get set }
}

Then, you can initialize your cells all the same way, but declare them as a ConfigurableCell : 然后,您可以用相同的方式初始化单元,但是将它们声明为ConfigurableCell

var cell: ConfigurableCell? = nil    // not set yet
if somePosts[indexPath.row].typeOfPost == .linkPost {
    cell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .picturePost {
    cell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .textPost {
    cell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell
} 

guard let cell = cell else {
    // how to handle this error case is up to you
    print("Type of post is not link, picture, or text")
    return UITableViewCell()    
}

// now, cell is a ConfigurableCell with a titleLabel property, regardless of class
cell.titleLabel.text = "Some title"

Of course, UITableViewCell does have a built-in textLabel property, which you could try to utilize in your cell classes, and then a protocol wouldn't be necessary, because the property is in UITableViewCell . 当然, UITableViewCell确实具有内置的textLabel属性,您可以尝试在单元格类中使用该属性,然后不需要协议,因为该属性位于UITableViewCell

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用带有自定义对象的Set类型作为数据源 - How to use a Set type with custom objects as datasource 如何在 switch 语句中将类型转换为枚举中的变量? - How to I cast a type to a variable in an enum within a switch statement? 在 Swift 中,如何声明符合一个或多个协议的特定类型的变量? - In Swift, how can I declare a variable of a specific type that conforms to one or more protocols? 如何使用带有关联类型的协议使用类型擦除 - How can I use Type Erasure with a protocol using associated type 我可以根据返回值使用设置的占位符类型吗? - Can I use set placeholder type based on return value? 如何在 Swift 中使用相同的变量名,但使用不同的数据类型 - how can I do to use same variable name, but different data type in Swift Swift:如何使用“ AnyClass”变量定义数组内部的类型? - Swift: how can I use an 'AnyClass' variable to define what type is inside an array? 如何检查是否启用了特定类型的本地通知? - How can I check if a specific type of local notification is enabled? 如何将NSMutableArray转换为特定类型的Swift数组? - How can I cast an NSMutableArray to a Swift array of a specific type? 如何检查通用变量的类型? - How can I check the type of my generic variable?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM