ios - 设置后委托(delegate)nil

标签 ios swift delegates

我正在使用委托(delegate)方法,但由于某些奇怪的原因,当我想调用委托(delegate)方法时,我的委托(delegate)变量似乎为 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,但是委托(delegate)方法甚至没有被调用,因为当我点击按钮时委托(delegate)为 nil

最佳答案

我喜欢保持我的自定义 View 模块化,并以编程方式做事,避免使用 Xib。

您应该将 View 的职责和 subview 保留在 View 本身。最终,接收操作的 View 应该负责调用委托(delegate)的方法。此外,nextView 是一个返回 UIView 的闭包:(() -> UIView?)? 不是 UIView,在闭包中调用函数不是显式返回您应该返回 View :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,但请记住在创建后设置它们中的每一个的 Delegate:

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

关于ios - 设置后委托(delegate)nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48727475/

相关文章:

ios - 如何启用苹果应用商店中的应用程序以在浏览器上查看?

ios - TableView 中的动态节数和行数

objective-c - Transient NSPopover 燕子先点击父窗口控件

ios - 两个日期之间的计时器倒计时

c# - 与 c# 中委托(delegate)声明的区别

c# - 为什么 .net 委托(delegate)赋值运算符没有将引用分配给原始委托(delegate)?

objective-c - NSString initWithBytes 结果在 iOS 上是错误的

iphone - 如何将图像缩放到全屏模式?

ios - 在 Swift 中,如何等待一个动画在下一个动画开始之前完成?

带有 out 参数的 c# 泛型委托(delegate) - 定义和调用