在视图外的单元格上更改背景颜色

时间:2017-05-31 14:48:41

标签: uitableview swift3 ios10 tableviewcell xcode8

我最近发现我的代码出错了,在做完所有事情后我都想到了解决它的问题,我能够弄清楚我相信会发生什么。在我的应用程序中,如果用户选择该单元格,我可以更改背景颜色,这样就可以选择多个单元格。但是如果选择了第一个单元格,它将取消选择(更改背景颜色)所有其他单元格。但事实证明我得到以下错误:

  

致命错误:在解包可选值时意外发现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的图像。 enter image description here

1 个答案:

答案 0 :(得分:0)

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

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
    }
}