swift 我的removeButton是不工作,在第一次当我运行应用程序

i7uaboj4  于 2023-04-19  发布在  Swift
关注(0)|答案(1)|浏览(131)

所以我创建的remove闭包可以工作,但一开始没有移动页面就有问题,它通过了函数,但闭包不工作。

var removeCell: ((SneakersTableCell) -> ())?
    var customView = CustomViewModel()
    var viewModel = Sneakers()
    
    override init(style: UITableViewCell.CellStyle,reuseIdentifier: String?) {
        super.init(style: .default,reuseIdentifier: "SneakersTableCell")
        print("New cell has been create")
        setupUI()
        setupConstraints()
        removeButton.addTarget(self, action: #selector(removeButtonTapped(_:)), for: .touchUpInside)
        wishButton.addTarget(self, action: #selector(wishButtonTapped(_:)), for: .touchUpInside)
        
    }
    
    @objc func removeButtonTapped(_ sender: UIButton) {
        print("Tapped remove button")
        removeCell?(self)
    }

这是在UITableViewCell中完成的部分

extension CustomTableViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return viewModel.sneakersClass.cart.count + 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch indexPath.row {
        case viewModel.sneakersClass.cart.count:
            guard let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier(for: .orderSummary)) as? OrderSummaryCell else {
                fatalError("Unable to dequeue OrderSummaryView cell")
            }
            return cell
        default:
            guard let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier(for: .sneakers)) as? SneakersTableCell else {
                fatalError("Unable to dequeue SneakersTableCell cell")
            }
            let product = viewModel.sneakersClass.cart[indexPath.row]
            cell.configure(product: product)
            cell.qtyButton.addTarget(self, action: #selector(openModal(_:)), for: .touchUpInside)
            cell.removeCell = { [weak self] aCell in
                guard let self = self,
                      let idxPath = self.tableView.indexPath(for: aCell),
                      let summaryCell = self.tableView.cellForRow(at: IndexPath(row: self.viewModel.sneakersClass.cart.count, section: 0)) as? OrderSummaryCell
                else { return }
                self.viewModel.sneakersClass.cart.remove(at: idxPath.row)
                self.tableView.deleteRows(at: [idxPath], with: .automatic)
                summaryCell.updateSummaryValues(viewModel: self.viewModel)
            }
            return cell
        }
    }
    
    @objc func openModal(_ sender: UIButton) {
        let modalViewController = ModalConfigurator().build(type: .quantity, gender: .women)
        modalViewController.modalPresentationStyle = .overFullScreen
        present(modalViewController, animated: false, completion: nil)
    }
}

下面的代码是相对于我的tableViewCell的:

import UIKit

final class SneakersTableCell: UITableViewCell {
    private let productImageView = UIImageView()
    private let categoryLabel = UILabel()
    private let nameLabel = UILabel()
    private let priceLabel = UILabel()
    private let sizeLabel = UILabel()
    private let colorLabel = UILabel()
    let removeButton = UIButton()
    private let clearImage = UIImage(systemName: "xmark")?.withTintColor(.label, renderingMode: .alwaysOriginal)
    var qtyButton = UIButton()
    private let arrowQty = UIImage(named: "Arrow_Qty")?.withRenderingMode(.alwaysTemplate)
    private let wishButton = UIButton()
    
    var removeCell: ((SneakersTableCell) -> ())?
    var customView = CustomViewModel()
    var viewModel = Sneakers()
    
    override init(style: UITableViewCell.CellStyle,reuseIdentifier: String?) {
        super.init(style: .default,reuseIdentifier: "SneakersTableCell")
        print("New cell has been create")
        setupUI()
        setupConstraints()
        removeButton.addTarget(self, action: #selector(removeButtonTapped(_:)), for: .touchUpInside)
        wishButton.addTarget(self, action: #selector(wishButtonTapped(_:)), for: .touchUpInside)
        
    }
    
    @objc func removeButtonTapped(_ sender: UIButton) {
        print("Tapped remove button")
        removeCell?(self)
    }
    
    @objc func wishButtonTapped(_ sender: UIButton) {
        print("Moved to wishlist")
    }

    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configure(product: Product) {
        productImageView.image = product.image
        categoryLabel.text = product.category
        nameLabel.text = product.name
        priceLabel.text = "\(product.price)€"
        sizeLabel.text = "Size: \(product.size)"
        colorLabel.text = "Color: \(product.color)"
    }
    
    private func setupUI() {
        selectionStyle = .none
        
        let array = [productImageView,
                     categoryLabel,
                     nameLabel,
                     priceLabel,
                     sizeLabel,
                     colorLabel,
                     removeButton,
                     qtyButton,
                     wishButton]
        
        array.forEach { view in
            view.translatesAutoresizingMaskIntoConstraints = false
            addSubview(view)
        }
        
        contentView.translatesAutoresizingMaskIntoConstraints = false
        
        productImageView.layer.cornerRadius = 16
        
        categoryLabel.font = FontStyle.uiS.baseUIFont
        categoryLabel.textColor = Color.grayScale400
        
        nameLabel.font = FontStyle.displayMBold.baseUIFont
        nameLabel.textColor = Color.grayScale700
        
        priceLabel.font = FontStyle.uiS.baseUIFont
        priceLabel.textColor = Color.grayScale700
        
        sizeLabel.font = FontStyle.uiXS.baseUIFont
        sizeLabel.textColor = Color.grayScale700
        
        colorLabel.font = FontStyle.uiXS.baseUIFont
        colorLabel.textColor = Color.grayScale700
        
        removeButton.setImage(clearImage, for: .normal)
        
        qtyButton.setTitle("Qty: 1 ", for: .normal)
        qtyButton.setImage(arrowQty, for: .normal)
        qtyButton.semanticContentAttribute = .forceRightToLeft
        qtyButton.layer.cornerRadius = 16
        qtyButton.backgroundColor = Color.grayScaleWhite
        qtyButton.setTitleColor(Color.grayScale700, for: .normal)
        qtyButton.layer.borderWidth = 1
        qtyButton.layer.borderColor = Color.grayScale200?.cgColor
        qtyButton.titleLabel?.font = FontStyle.uiM.baseUIFont
        qtyButton.tintColor = Color.grayScale700
        
        wishButton.setTitle("Move to wishlist", for: .normal)
        wishButton.setTitleColor(Color.grayScale700, for: .normal)
        wishButton.titleLabel?.font = FontStyle.uiM.baseUIFont
        
        let attributedTitle = NSAttributedString(string: "Move to wishlist", attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue])
        wishButton.setAttributedTitle(attributedTitle, for: .normal)
    }
    
    private func setupConstraints() {
        NSLayoutConstraint.activate([
            contentView.heightAnchor.constraint(equalToConstant: 274),
            
            productImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 32),
            productImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
            productImageView.widthAnchor.constraint(equalToConstant: 106),
            productImageView.heightAnchor.constraint(equalToConstant: 114),
            
            categoryLabel.topAnchor.constraint(equalTo: productImageView.topAnchor, constant: 18),
            categoryLabel.leadingAnchor.constraint(equalTo: productImageView.trailingAnchor, constant: 32),
            
            nameLabel.topAnchor.constraint(equalTo: categoryLabel.bottomAnchor, constant: 8),
            nameLabel.leadingAnchor.constraint(equalTo: productImageView.trailingAnchor, constant: 32),
            nameLabel.widthAnchor.constraint(equalToConstant: 159),
            nameLabel.heightAnchor.constraint(equalToConstant: 24),
            
            priceLabel.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: 8),
            priceLabel.leadingAnchor.constraint(equalTo: productImageView.trailingAnchor, constant: 32),
            priceLabel.widthAnchor.constraint(equalToConstant: 56),
            priceLabel.heightAnchor.constraint(equalToConstant: 14),
            
            sizeLabel.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 16),
            sizeLabel.leadingAnchor.constraint(equalTo: productImageView.trailingAnchor, constant: 32),
            sizeLabel.widthAnchor.constraint(equalToConstant: 46),
            sizeLabel.heightAnchor.constraint(equalToConstant: 12),
            
            colorLabel.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 16),
            colorLabel.leadingAnchor.constraint(equalTo: sizeLabel.trailingAnchor, constant: 16),
            colorLabel.widthAnchor.constraint(equalToConstant: 62),
            colorLabel.heightAnchor.constraint(equalToConstant: 12),
            
            removeButton.topAnchor.constraint(equalTo: productImageView.topAnchor),
            removeButton.trailingAnchor.constraint(equalTo: trailingAnchor,constant: -24),
            removeButton.widthAnchor.constraint(equalToConstant: 12),
            removeButton.heightAnchor.constraint(equalToConstant: 12),
            
            qtyButton.topAnchor.constraint(equalTo: productImageView.bottomAnchor, constant: 32),
            qtyButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 32),
            qtyButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant:20),
            qtyButton.widthAnchor.constraint(equalToConstant: 106),
            qtyButton.heightAnchor.constraint(equalToConstant: 64),
            
            wishButton.centerYAnchor.constraint(equalTo: qtyButton.centerYAnchor),
            wishButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant:-20),
            wishButton.widthAnchor.constraint(equalToConstant: 116),
            wishButton.heightAnchor.constraint(equalToConstant: 16),
        ])
    }
}

这一个是在一个TableView里面的cellForRowAt方法。你能帮我找到问题吗?
当我第一次启动应用程序时,remove函数可以工作,但闭包不行
First!

pbpqsu0x

pbpqsu0x1#

UITableViewcellForRow:at:将返回nil,如果该行不可见,预取或缓存。因此,如果该单元格尚未从数据源中获取,则guard语句将返回。这解释了为什么当您将表滚动到足够远以获取汇总单元格时(它可能是预取的,但不一定是可见的),delete闭包就可以工作。
您的代码应单独处理汇总行,如果找不到单元格,则不执行任何操作:

cell.removeCell = { [weak self] aCell in
    guard let self = self,
          let idxPath = self.tableView.indexPath(for: aCell)
    else { return }
    
    // This is optional and will be nil if the cell is not visible (or pre-fetched, or cached)
    // We get this before deleting the item as the delete will adjust `count` 
    let summaryCell = self.tableView.cellForRow(at: IndexPath(row: self.viewModel.sneakersClass.cart.count, section: 0)) as? OrderSummaryCell
    
    self.viewModel.sneakersClass.cart.remove(at: idxPath.row)
    self.tableView.deleteRows(at: [idxPath], with: .automatic)

    // Now the item has been deleted we can update the summary cell (if we have one)
    summaryCell?.updateSummaryValues(viewModel: self.viewModel)

}

相关问题