我正在使用委托方法,但由于某些奇怪的原因,当我想调用委托方法时,我的委托变量似乎是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
答案 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.
}
}