如何禁用 Tableview DequeueReusableCell?

How to disable Tableview DequeueReusableCell?

我试图在不使用 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
    }
}

您有一个 class,其中 @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
}

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

不用说,不推荐这种模式,因为您失去了故事板单元原型的好处和 performance/memory 单元重用的好处。但是,如果您的目标只是比较和对比内存、性能和软件设计注意事项,也许这有助于您了解它。


虽然我试图回答您的问题,但在我担心出列单元格的固有性能之前,您的图像检索机制是一个更大的性能问题。您正在使用不可取消的网络请求 Data(contentsOf:) 获取图像。因此,如果您有一百行,并且您快速向下滚动到第 90..<100 行,那么这 10 行的图像检索将积压为前 90 行的网络请求!此外,您的图像大小是否适合单元格中的小图像视图?这也会显着影响性能和滚动的平滑度。

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

但是 table 视图的正确异步图像检索是一个非常重要的问题。 AlamofireImageKingFisher、SDWebImage等图像处理库,可以为你简化这个过程。