【问题标题】:Changing Background color on Cell outside of view更改视图外单元格的背景颜色
【发布时间】:2017-05-31 14:48:40
【问题描述】:

我最近发现我的代码有一个错误,在尽我所能解决它之后,我能够弄清楚我认为正在发生的事情。在我的应用程序中,如果用户选择该单元格,我会更改背景颜色,这样您就可以选择多个单元格。但是,如果选择了第一个单元格,它将取消选择(更改背景颜色)所有其他单元格。但事实证明我收到以下错误:

致命错误:在展开可选值时意外发现 nil

当我尝试更改屏幕上不可见的单元格的背景颜色时。我假设这是因为只有可见单元格被加载到内存中,而所有其他单元格只有在它们再次可见时才会被加载。

那么我将如何手动加载一个我知道 IndexPath 但也知道它在视图之外的单元格。另外,有没有办法知道 IndexPath 处的单元格是否已加载?

这是我当前的代码。

func selectAnyList(tableView: UITableView) {

    let sections = frc!.sections!
    let currentSection = sections[0]
    let numRows = currentSection.numberOfObjects

    for i in 0...(numRows - 1) {
        let indexPath = IndexPath(row: i, section: 0)

        let cell = tableView.cellForRow(at: indexPath) as! ItemListTVCell   //This is where the error happens if the cell is not visible
        if (i == 0) {
            cell.backgroundColor = UIColor.activeAqua.withAlphaComponent(0.85)
        } else {
            cell.backgroundColor = UIColor.white.withAlphaComponent(0.85)
        }
    }
}

编辑:添加单元格的加载方式

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

    let list: Ent_Lists = frc!.object(at: indexPath)
    let cell = tableView.dequeueReusableCell(withIdentifier: "itemListCell", for: indexPath) as! ItemListTVCell

    if (list == Ent_Lists.anyList) {
        self.anyCell = cell
    }

    cell.listName.text = list.name
    cell.listImage.image = list.image!.uiImage

    if ((indexPath as NSIndexPath).row != 0 && listSet!.contains(list)) {
        numLists += 1
    }

    return cell
}

Edit2:在 Coredata 中添加了 Ent_List 的图像。

【问题讨论】:

  • 您的列表中是否有一些模型的数组?如果是,请添加一个名为 bgColor 的额外属性,并对其进行更新。
  • 我还是个很绿色的程序员,我不确定我是否理解你的建议。
  • 你能展示一下Ent_Lists 的样子吗?
  • 添加了来自 Coredata 的 Ent_Lists 的图像
  • 您是否总是希望第一个单元格的背景颜色不同?或者它可以是任何单元格,其 bg 颜色应该与其他单元格不同?

标签: uitableview swift3 ios10 tableviewcell xcode8


【解决方案1】:

我创建了一个小示例文件,您可以在其中动态设置背景颜色,并且每次您选择的背景颜色都会有不同的背景颜色。

import UIKit

// This is your core data entity
struct Entity {
    let title: String
}

// This is a basic viewModel, holding the selected property and the core data entity
class EntityViewModel {
    let entity: Entity
    // Set the selected property to false
    var selected: Bool = false

    init(entity: Entity) {
        self.entity = entity
    }
}

class TableViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    lazy  fileprivate var entityViewModels: [EntityViewModel] = self.makeEntityViewModels(count: 20)

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.delegate = self

    }
}

extension TableViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return entityViewModels.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        // Work with viewModels, instead of the CoreData entities directly
        let viewModel = entityViewModels[indexPath.row]
        // Set the title of the cell
        cell.textLabel?.text = viewModel.entity.title
        // Based on the selected property, set the background color
        cell.backgroundColor = viewModel.selected ? .black : .yellow
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // Reset the selection for all viewModels
        entityViewModels.forEach { 
            $0.selected = false
        }

        // Get the viewModel at the right indexPath
        let viewModel = entityViewModels[indexPath.row]
        // Set its selected state to true
        viewModel.selected = true
        // Reload the tableView -> this will trigger `cellForRowAt`, and your background colors will be up to date
        self.tableView.reloadData()
    }
}

extension TableViewController {
    // This is where you read up from core data
    private func makeEntities(count: Int) -> [Entity] {
        var entities: [Entity]  = []
        for index in 0..<count {
            entities.append(Entity(title: "\(index) Some title"))
        }
        return entities
    }
    // Just wrap the core data objects into viewModels
    func makeEntityViewModels(count: Int) -> [EntityViewModel] {
        let entities = makeEntities(count: count)
        var viewModels: [EntityViewModel] = []
        for (index, entity) in entities.enumerated() {
            let viewModel = EntityViewModel(entity: entity)
            // Intialy, set the first viewModel to selected
            if index == 0 {
                viewModel.selected = true
            }
            viewModels.append(viewModel)
        }
        return viewModels
    }
}

【讨论】:

  • 谢谢,我试试看
  • @JasonBrady 我已经修改了makeEntityViewModels 函数,所以在设置viewModels时将选择第一项。
  • 再次感谢您。我现在在上班,所以我今晚试试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
  • 2013-04-12
  • 2021-10-31
  • 2016-05-27
  • 1970-01-01
  • 2013-06-15
相关资源
最近更新 更多