我正在使用委托(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.
}
}
关于ios - 设置后委托(delegate)nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48727475/