设置后委派nil

时间:2018-02-11 01:49:57

标签: ios swift delegates

我正在使用委托方法,但由于某些奇怪的原因,当我想调用委托方法时,我的委托变量似乎是nil。我不能为我的生活弄清楚我做错了什么

protocol ProfileProtocol {
    func buttonTapped()
}

class ProfileView: UIView {

    var delegate: ProfileProtocol?

    @IBOutlet weak var button: UIButton!

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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    override func awakeFromNib() {
        configure()
    }

    func setup() {        

        ...
    }


    @IBAction func buttonTapped(_ sender: UIButton) {
        // delegate nil
        delegate?.buttonTapped()
    }

}

ProfileViewController(是的,它符合ProfileProtocol):

override func viewDidLoad() {
    swipeableView.nextView = {
       createCardView()
    }
}

func createCardView() -> UIView {        
    let cardView = ProfileView(frame: swipeableView.bounds)
    cardView.delegate = self

    let contentView = Bundle.main.loadNibNamed("ProfileCardView", owner: self, options: nil)?.first! as! UIView
    contentView.translatesAutoresizingMaskIntoConstraints = false
    contentView.backgroundColor = cardView.backgroundColor
    cardView.addSubview(contentView)

    activeCardView = cardView
    return cardView
}

func buttonTapped() {
    self.performSegue(withIdentifier: "profileToEmojiCollection", sender: self)
}

每当我点击ProfileView中的按钮时,我的ProfileViewController应该执行一个segue,但是当我点击按钮时,委托方法甚至没有被调用,因为委托是nil

1 个答案:

答案 0 :(得分:1)

我喜欢将自定义视图保持模块化,并以编程方式执行操作,避免使用Xib。

您应该将视图的职责和子视图保留在视图本身中。最终,接收动作的视图应该负责调用委托的方法。另外nextView是一个返回UIView的闭包:(() -> UIView?)?而不是UIView,对闭包中函数的调用不是显式返回,你应该返回视图:let view = createCardView() return view

<强> ProfileView.swift

import UIKit

protocol ProfileProtocol {
    func buttonTapped()
}

class ProfileView: UIView {

    var delegate: ProfileProtocol?


    lazy var button: UIButton = {
        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
        button.setTitle("Profile Button", for: .normal)
        button.backgroundColor = UIColor.black
        return button
    }()

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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func awakeFromNib() {

    }


    @objc func buttonTapped(_ sender: UIButton) {
        // Check for a nil delegate, we dont want to crash if one is not set
        if delegate != nil {
            delegate!.buttonTapped()
        } else {
            print("Please set ProfileView's Delegate")
        }
    }

    func setup() {
        //setup subviews
        self.addSubview(button)

        button.widthAnchor.constraint(equalToConstant: 150).isActive = true
        button.heightAnchor.constraint(equalToConstant: 50).isActive = true
        button.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true

    }

}

您可以像创建任何其他UIView一样创建ProfileView,但请记住在创建后设置每个U的代理:

swipeableView.nextView = {
    let view = createProfileView() //set properties during creation?
    view.delegate = self 
    //set properties after creation?
    //view.backgroundColor = UIColor.red
    return view
 }

<强> ViewController.swift

import UIKit

class ViewController: UIViewController, ProfileProtocol {

    lazy var profileView: ProfileView = {
        let view = ProfileView()
        view.backgroundColor = UIColor.lightGray
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        profileView.delegate = self


        setup()
    }

    func buttonTapped() {
        print("Do Something")
    }


    func setup() {
        self.view.addSubview(profileView)
        profileView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
        profileView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.7).isActive = true
        profileView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        profileView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true

    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Image of View Hierarchy