从单元格

时间:2018-06-18 18:08:57

标签: ios swift uitableview tableview

我有一个细胞类' NewsCell' (UITableViewCell的子类)我用于两种不同的新闻:OrganizationNews和ProjectNews。这些新闻有共同点,但有些元素不同。也就是说,当我的单元格用于ProjectNews时,我想隐藏组织的标识,当它用于OrganizationNews时,我想隐藏项目的名称按钮。

我有'configureCell(_,forNews,ofProject)'方法。我在' NewsViewController'中称呼它。我使用了' removeFromSuperview'方法,因为我需要在' NewsCell'中重新安排我的元素。改变'隐藏'价值不会给我带来这种效果。

所以,这就是问题所在。我有'线程1:致命错误:在解开一个Optional值时意外发现nil'行projectNameButton.removeFromSuperview()或logoImageView.removeFromSuperview()中的异常。 我该怎么办?

// NewsViewController.swift
func configureCell(_ cell: NewsCell, forNews news: News, ofProject project: Project? = nil) {
    //...
    if news is OrganizationNews {
        cell.projectNameButton.removeFromSuperview()
    } else if news is ProjectNews {
        cell.logoImageView.removeFromSuperview()
    }
    // ...
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let news = newsCollection[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCellIdentifiers.newsCell, for: indexPath) as! NewsCell
    configureCell(cell, forNews: news)
    cell.delegate = self
    return cell
}

3 个答案:

答案 0 :(得分:0)

更改删除行,如下所示

if news is OrganizationNews {
    cell.projectNameButton?.removeFromSuperview()
} else if news is ProjectNews {
    cell.logoImageView?.removeFromSuperview()
}

这将解决问题。但一个好的方法是为每个单元格创建单独的类。您可以创建一个基类来保持公共逻辑。

答案 1 :(得分:0)

UITableView或UICollectionView构建于 重用 概念之上,当您处理单元格时,这些单元格将被重用并重新填充。

当您尝试调用dequeReusableCell(withIdentifier:)时,它有时会返回之前创建的内容。所以,假设你在拥有所有控制权的东西之前进行了dequed,然后删除了一个(removeFromSuperview),然后再次尝试deque,新的dequed可能没有子视图。

我认为最适合您的解决方案是制作两个不同的单元格。

<强> 实施例

class BaseNewsCell: UITableViewCell {
    // Put the common views here
}

class OrganizationNewsCell: BaseNewsCell {
    // Put here things that are ONLY for OrganizationNewsCell
}

class ProjectNewsCell: BaseNewsCell {
    // Put here things that are ONLY for ProjectNewsCell
}

然后通过两个不同的故事板单元xibs从2个不同的标识符中取消它们。

或者

class BaseNewsCell: UITableViewCell {
    // Put the common views here
}

class OrganizationNewsCell: BaseNewsCell {
    // This happens when this kind of cell is created for the first time
    override func awakeFromNib() {
        super.awakeFromNib()
        someNonCommon.removeFromSuperview()
    }
}

class ProjectNewsCell: BaseNewsCell {
    override func awakeFromNib() {
        super.awakeFromNib()
        someOtherNonCommon.removeFromSuperview()
    }
}

注意: 这违反了Liskov的原则(SOLID原则之一),因为您从子类中的超类中删除了功能。

答案 2 :(得分:0)

您不应该从单元格的外部中删除子视图。让我们重构您的代码。

<强> NewsCell.swift

final class NewsCell: UITableViewCell {
    enum Kind {
        case organization
        case project
    }

    var logoImageView: UIImageView?
    let nameLabel = UILabel()

    var kind: NewsCell.Kind {
        didSet {
            if kind != oldValue {
                setupLogoImageView()
                self.setNeedsLayout()
            }
        }
    }

    init(kind: NewsCell.Kind, reuseIdentifier: String?) {
        self.kind = kind
        super.init(style: .default, reuseIdentifier: reuseIdentifier)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

// MARK: - Positioning
extension NewsCell {
    override func layoutSubviews() {
        super.layoutSubviews()

        // Your layouting
        switch kind {
            case .organization:
                // Setup frame for organization typed NewsCell
            case .project:
                // Setup frame for project typed NewsCell
        }
    }
}

// MARK: - Setup
extension NewsCell {
    private func setupLogoImageView() {
        logoImageView = kind == .organization ? UIImageView() : nil
    }
}

使用方法:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let news = newsCollection[indexPath.row]

    var cell = tableView.dequeueReusableCell(withIdentifier: TableViewCellIdentifiers.newsCell) as? NewsCell
    if cell == nil {
        cell = NewsCell(kind: .organization, reuseIdentifier: TableViewCellIdentifiers.newsCell)
    }

    cell!.kind = news is Organization ? .organization: .project

    return cell!
}