Swift-通过委托传递变量

时间:2019-12-16 00:03:55

标签: ios swift uitableview delegates

我基本上想传递一个数组索引,但是我收到一条错误消息,并且无法解决问题。

我要访问的索引在我的dropDownViewdidSelectRowAt)内部。

class dropDownView: UIView, UITableViewDelegate, UITableViewDataSource  {



var dropDownOptions = [String]()

var tableView = UITableView()

var delegate : dropDownProtocol!

var selectedWishlistDelegate: selectedWishlistProtocol!

override init(frame: CGRect) {
    super.init(frame: frame)

    tableView.backgroundColor = UIColor.lightGray
    self.backgroundColor = UIColor.lightGray


    tableView.delegate = self
    tableView.dataSource = self

    tableView.translatesAutoresizingMaskIntoConstraints = false

    self.addSubview(tableView)

    tableView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
    tableView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
    tableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell()

    cell.textLabel?.text = dropDownOptions[indexPath.row]
    cell.backgroundColor = UIColor.lightGray
    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    self.delegate.dropDownPressed(string: dropDownOptions[indexPath.row])

    self.selectedWishlistDelegate.didSelectWishlist(idx: indexPath.row) // fatal error

    self.tableView.deselectRow(at: indexPath, animated: true)
}

}

//MARK: Protocols

protocol selectedWishlistProtocol {
    func didSelectWishlist(idx: Int)
}

要在我的ExampleViewController中访问它,我尝试了以下操作:

    extension ExampleViewController: selectedWishlistProtocol{
    func didSelectWishlist(idx: Int) {
        self.selectedWishlistIDX = idx
    }
}

现在我收到此错误:

  

线程1:致命错误:在隐式展开一个可选值时意外发现nil

为什么indexPath.row nil ??上面的delegate可以正常工作。

可能是初学者的错误,因为我对delegates不太满意,但我对每次帮助都很感激:)

更新

我在我的DropDownBtn`类中实例化了dropDownView

class DropDownBtn: UIButton, DropDownProtocol {

func dropDownPressed(string: String) {
    self.setTitle(string, for: .normal)
    self.dismissDropDown()
}

var dropView = DropDownView()

var height = NSLayoutConstraint()


override init(frame: CGRect) {
    super.init(frame: frame)

    self.backgroundColor = UIColor.lightGray

    dropView = DropDownView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0))
    dropView.delegate = self
    dropView.translatesAutoresizingMaskIntoConstraints = false
}

override func didMoveToSuperview() {
    self.superview?.addSubview(dropView)
    self.superview?.bringSubviewToFront(dropView)
    dropView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    dropView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
    dropView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
    height = dropView.heightAnchor.constraint(equalToConstant: 0)
}

var isOpen = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if isOpen == false {

        isOpen = true

        NSLayoutConstraint.deactivate([self.height])

        if self.dropView.tableView.contentSize.height > 150 {
            self.height.constant = 150
        } else {
            self.height.constant = self.dropView.tableView.contentSize.height
        }


        NSLayoutConstraint.activate([self.height])

        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
            self.dropView.layoutIfNeeded()
            self.dropView.center.y += self.dropView.frame.height / 2
        }, completion: nil)

    } else {
        isOpen = false

        NSLayoutConstraint.deactivate([self.height])
        self.height.constant = 0
        NSLayoutConstraint.activate([self.height])
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
            self.dropView.center.y -= self.dropView.frame.height / 2
            self.dropView.layoutIfNeeded()
        }, completion: nil)

    }
}

func dismissDropDown() {
    isOpen = false
    NSLayoutConstraint.deactivate([self.height])
    self.height.constant = 0
    NSLayoutConstraint.activate([self.height])
    UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
        self.dropView.center.y -= self.dropView.frame.height / 2
        self.dropView.layoutIfNeeded()
    }, completion: nil)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

2 个答案:

答案 0 :(得分:2)

确定

var selectedWishlistDelegate:SelectedWishlistProtocol!

不是nil,这意味着在实例化设置视图时

let v = DropDownView()
v.selectedWishlistDelegate = // some value 

答案 1 :(得分:1)

此处的最佳做法是使您的delegatelistener引用为可选。在这里,您是force unwrapping selectedWishlistDelegate,而没有先设置它。通过在声明!后使用selectedWishlistDelegate,您可以断言该引用不会为nil,但似乎是。这会导致运行时错误,并使您的应用程序崩溃。

要解决此问题,请对此进行更改:

var delegate : dropDownProtocol!

var selectedWishlistDelegate: selectedWishlistProtocol!

对此:

var delegate : dropDownProtocol?

var selectedWishlistDelegate: selectedWishlistProtocol?

这:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    self.delegate.dropDownPressed(string: dropDownOptions[indexPath.row])

    self.selectedWishlistDelegate.didSelectWishlist(idx: indexPath.row) // fatal error

    self.tableView.deselectRow(at: indexPath, animated: true)
}

对此:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    self.delegate?.dropDownPressed(string: dropDownOptions[indexPath.row])

    self.selectedWishlistDelegate?.didSelectWishlist(idx: indexPath.row) // fatal error

    self.tableView.deselectRow(at: indexPath, animated: true)
}

然后您需要更改:

class DropDownBtn: UIButton, DropDownProtocol {

收件人:

class DropDownBtn: UIButton, DropDownProtocol, selectedWishlistProtocol {
    func didSelectWishlist(idx: indexPath.row) {
        self.selectedWishlistIDX = idx
    }

最后,您应该设置``,以便更改此内容:

override init(frame: CGRect) {
    super.init(frame: frame)

    self.backgroundColor = UIColor.lightGray

    dropView = DropDownView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0))
    dropView.delegate = self
    dropView.translatesAutoresizingMaskIntoConstraints = false
}

对此:

override init(frame: CGRect) {

    super.init(frame: frame)

    self.backgroundColor = UIColor.lightGray

    dropView = DropDownView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0))
    dropView.delegate = self
    dropView.selectedWishlistDelegate = self
    dropView.translatesAutoresizingMaskIntoConstraints = false
}

如果您尚未设置selectedWishlistDelegate,这将保护您的应用程序不会崩溃,并使您可以更轻松地测试视图的功能。