如何禁用 Tableview DequeueReusableCell?

Posted

技术标签:

【中文标题】如何禁用 Tableview DequeueReusableCell?【英文标题】:How to disable Tableview DequeueReusableCell? 【发布时间】:2021-01-10 14:11:40 【问题描述】:

我试图在不使用 dequeueReusableCell 的情况下加载我的 tableview,但它只是让我的应用程序崩溃,无法弄清楚我做错了什么?

let cell = Tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SökrutaCell       // THIS CODE WORKS FINE
        
let cell = SökrutaCell() // THIS CODE CRASHES - Unexpectedly found nil while unwrapping an optional

如果有人能指出我正确的方向,我会很高兴,这样我就可以理解失败的原因。

import UIKit
import Alamofire

class Sökruta: UIViewController 
    
    var sökresultat = [Object2]()
    @IBOutlet weak var Tableview: UITableView!
    
    override func viewDidLoad() 
        super.viewDidLoad()
        
        GetRequest(Url: "https://randomurl.se")

        Tableview.delegate = self
        Tableview.dataSource = self
        Tableview.backgroundColor = UIColor.white
        // Do any additional setup after loading the view.
    


// MARK: - Delegate extension 1
extension Sökruta: UITableViewDelegate
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        print("you tapped me!")
    


// MARK: - Delegate extension 2
extension Sökruta: UITableViewDataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return sökresultat.count
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        //  let cell = Tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SökrutaCell       // THIS CODE WORKS FINE
        
        let cell = SökrutaCell()   // THIS CODE CRASHES - Unexpectedly found nil while unwrapping an optional
        
        cell.Söknamn.text = sökresultat[indexPath.row].displayname
        
        if let url = URL(string: dontmindthiscode) 
            
            DispatchQueue.global().async 
                do 
                    let data = try Data(contentsOf: url)
                    DispatchQueue.main.async 
                        cell.Sökbild.image = UIImage(data: data)
                    
                 catch let err 
                    print("error: \(err.localizedDescription)")
                
            
        
        else
        
            DispatchQueue.main.async 
                cell.Sökbild.image = UIImage(systemName: "eye.slash")
            
        
        
        return cell
    


// MARK: - Extension functions
extension Sökruta
        
    // MARK: - GET REQUEST
    func GetRequest(Url: String)  

        // MARK: - Login details
        let headers: HTTPHeaders = [
            .authorization(username: "username", password: "password"),
            .accept("application/json")]
        
        // MARK: - Api request
        AF.request(result, headers: headers).validate().responseJSON  response in
            
            // MARK: - Check for errors
            if let error = response.error
            
                print (error)
                return
            
            // MARK: - Print response
            if response.response != nil
             
            
            // MARK: - Print data
            if response.data != nil
            
                let decoder = JSONDecoder()
                do
                
                    let api = try decoder.decode(Main2.self, from: response.data!)
                
                    self.sökresultat = api.objects
                
                    self.Tableview.reloadData()
                
               
                catch 
                    print(error.localizedDescription)
                    print("Error in JSON parsing")
                
            
        
    // MARK: - END

这是我的 cell.swift 代码:

import UIKit

class SökrutaCell: UITableViewCell 
    @IBOutlet weak var Sökbild: UIImageView!
    @IBOutlet weak var Söknamn: UILabel!

    override func awakeFromNib() 
        super.awakeFromNib()
        // Initialization code
    

    override func setSelected(_ selected: Bool, animated: Bool) 
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    

【问题讨论】:

还有其他关于这个问题的讨论:例如***.com/questions/43487865/… 不重用单元格是非常非常糟糕的做法。不要那样做。 为什么不想出队/重用?它更有效(并且在这里避免了您的问题)。 您的单元是在 NIB/XIB 还是故事板单元原型中定义的? @rob 嘿!据我所知,我没有 Xib/Nib 文件,它都放在故事板中。我想禁用重用功能的原因是因为我想了解它是如何工作的,并查看性能差异。 【参考方案1】:

您有一个类,其中 @IBOutlet 引用了故事板中的原型单元格。除非您使用dequeueReusableCell(withIdentifier:for:),否则您不能使用该单元原型(具有自定义布局)并为您连接插座。

如果您的目标是将其与未重复使用的单元格进行比较,您可以通过编程方式实例化 UITableViewCell 并使用内置的 textLabelimageView 属性。例如,您可以:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = UITableViewCell(style: .default, reuseIdentifier: "...")

    cell.textLabel?.text = ...
    cell.imageView?.image = ...  // use a placeholder image here or else it won't show the image view at all!

    someMethodToFetchImageAsynchronously  image in
        // make sure this cell hasn't scrolled out of view!!!
        guard let cell = tableView.cellForRow(at: indexPath) else  return 
    
        // if still visible, update its image
        cell.imageView?.image = image
    
    return cell

或者您也可以考虑更复杂的编程模式(在其中添加控件并手动配置它们,这可能是一个更公平的比较)。但以上是一个相当简单的实现。

不用说,不推荐使用这种模式,因为您会失去故事板单元原型的好处以及单元重用的性能/内存好处。但是,如果您的目标只是比较和对比内存、性能和软件设计考虑因素,也许这有助于您掌握它。


虽然我试图回答您的问题,但在我担心出队单元的固有性能之前,您的图像检索机制是一个更大的性能问题。您正在使用Data(contentsOf:) 获取图像,这是一个不可取消的网络请求。因此,如果您有一百行,并且您快速向下滚动到第 90..

那里有许多不错的异步图像检索库。例如。由于您已经在使用 Alamofire,我建议您考虑 AlamofireImage。这提供了很好的异步图像检索机制、很好的UIImageView 扩展、取消不再需要的请求的能力、图像缓存等。

但是对于表视图进行适当的异步图像检索是一个不小的问题。 AlamofireImage、KingFisher、SDWebImage 等图像处理库可以为您简化此过程。

【讨论】:

非常感谢您花时间帮助我理解这一点,以及有关图像检索的额外提示。我一直在研究如何让我的代码运行得更好/更高效,修复图像检索部分肯定会有所帮助。

以上是关于如何禁用 Tableview DequeueReusableCell?的主要内容,如果未能解决你的问题,请参考以下文章

如何临时禁用tableview上的滚动

进入视图时如何禁用 TableView 单元格图像下载

QML:如何在 TreeView 和 TableView 禁用边框?

如何在 Popover 的 TableView 选择中禁用动画?

键盘存在时禁用 TableView 交互

如何禁用 tableview 特定行但特定行包含 uibutton。按钮必须访问