选择器未触发委托方法
Delegate method not being triggered by selector
我将 Class A 中的选择器传递给 Class B 中的方法,最终触发 Class A 中的 PressedButtonForMethodA
委托方法。但是,我认为我的选择器有问题,因为委托方法或 ClassB 的 PressedButtonForMethodA()
(ClassB.PressedButtonForMethodA() 仅用于调试目的)都没有被执行。使用 Swift 3 且没有故事板。这是我在 swift 操场上拥有的东西:
import UIKit
import PlaygroundSupport
class classA: UIViewController, ClassBDelegate {
private func setNavbarButtons() {
let myBarButton = classB()
myBarButton.delegate = self
let myBarButtonItem = myBarButton.setup("Press This", #selector(PressedButtonForMethodA))
self.navigationItem.rightBarButtonItem = myBarButtonItem
}
func PressedButtonForMethodA() {
NSLog("Method A in Class A fired!") // <<--THIS METHOD NOT BEING CALLED
}
}
protocol ClassBDelegate {
func PressedButtonForMethodA()
}
class classB: UIView {
var delegate: ClassBDelegate?
func setup(_ title: String, _ selectorAction: Selector) -> UIBarButtonItem {
let shadow = NSShadow()
shadow.shadowColor = UIColor.clear
let attributesNormal = [
NSForegroundColorAttributeName : UIColor.white,
NSShadowAttributeName : shadow,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 12.0)
]
let button = UIButton(type: .custom)
let buttonTitleAttributesNormal = NSAttributedString(string: title,
attributes: attributesNormal)
button.setAttributedTitle(buttonTitleAttributesNormal, for: UIControlState.normal)
let buttonTextSize = button.intrinsicContentSize
button.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width, height: buttonTextSize.height)
button.addTarget(self, action: selectorAction, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
return barButtonItem
}
func PressedButtonForMethodA() {
NSLog("Method A in Class B fired!") // <<-- THIS METHOD NOT FIRED EITHER
delegate?.PressedButtonForMethodA()
}
}
let myBarButtonItem = myBarButton.setup("Press This", #selector(PressedButtonForMethodA))
应该是
let myBarButtonItem = myBarButton.setup("Press This", #selector(myBarButton.PressedButtonForMethodA))
在设置方法中,当您应该从 ClassB 传递选择器时,您从 ClassA 传递选择器,因为您在此处添加了 self
作为目标:
button.addTarget(self, action: selectorAction, for: .touchUpInside)
完成编辑:
我对此进行了更多思考,并尝试了几种实现方式,并提出了两个合理的选择。不确定这两种方法是否会被考虑 "better," 但我想我会倾向于方法 #1。我认为它更 self-contained,并且不需要 Delegate 符合。 (忽略我的另一个答案,如果你看到它......我将两者合二为一)。
方法一
classB 是 UIBarButtonItem 的子类。调用 setup() 传递标题、Selector/Action(self 中的函数)和对 self 的引用(将用作按钮操作的目标)。
class ClassAB: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setNavbarButtons()
}
private func setNavbarButtons() {
let myBarButton = classB()
myBarButton.setup("Press Me AB", #selector(ClassAB.PressedButtonForMethodAB), self)
self.navigationItem.rightBarButtonItem = myBarButton
}
func PressedButtonForMethodAB() {
NSLog("Method AB in Class AB fired!")
}
}
class classB: UIBarButtonItem {
func setup(_ title: String, _ selectorAction: Selector, _ target: Any) {
let shadow = NSShadow()
shadow.shadowColor = UIColor.clear
let attributesNormal = [
NSForegroundColorAttributeName : UIColor.white,
NSShadowAttributeName : shadow,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 12.0)
]
let button = UIButton(type: .custom)
let buttonTitleAttributesNormal = NSAttributedString(string: title, attributes: attributesNormal)
button.setAttributedTitle(buttonTitleAttributesNormal, for: UIControlState.normal)
let buttonTextSize = button.intrinsicContentSize
button.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width, height: buttonTextSize.height)
// my navbar is white...
button.backgroundColor = UIColor.blue
// target and action both assigned by the creator (in this case, ClassAB)
button.addTarget(target, action: selectorAction, for: .touchUpInside)
customView = button
}
}
方法#2
classC 是 UIBarButtonItem 的子类。调用 setup() 传递标题,并将 self 指定为 classC 的委托。在 classC 内部,按钮 Action 是一个 class-level func,它依次调用定义的委托函数。
class ClassAC: UIViewController, ClassCDelegate {
override func viewDidLoad() {
super.viewDidLoad()
setNavbarButtons()
}
private func setNavbarButtons() {
let myBarButton = classC()
myBarButton.setup("Press Me AC")
myBarButton.delegate = self
self.navigationItem.rightBarButtonItem = myBarButton
}
func PressedButtonForMethodAC() {
NSLog("Method AC in Class AC fired!")
}
}
protocol ClassCDelegate {
func PressedButtonForMethodAC()
}
class classC: UIBarButtonItem {
var delegate: ClassCDelegate?
func setup(_ title: String) {
let shadow = NSShadow()
shadow.shadowColor = UIColor.clear
let attributesNormal = [
NSForegroundColorAttributeName : UIColor.white,
NSShadowAttributeName : shadow,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 12.0)
]
let button = UIButton(type: .custom)
let buttonTitleAttributesNormal = NSAttributedString(string: title, attributes: attributesNormal)
button.setAttributedTitle(buttonTitleAttributesNormal, for: UIControlState.normal)
let buttonTextSize = button.intrinsicContentSize
button.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width, height: buttonTextSize.height)
// my navbar is white...
button.backgroundColor = UIColor.blue
// target is self, selector action is inside self... *that* is where we'll call back to the delegate
button.addTarget(self, action: #selector(classC.classCTap), for: .touchUpInside)
customView = button
}
func classCTap() {
NSLog("tap inside ClassC ... call back to delegate method")
delegate?.PressedButtonForMethodAC()
}
}
我将 Class A 中的选择器传递给 Class B 中的方法,最终触发 Class A 中的 PressedButtonForMethodA
委托方法。但是,我认为我的选择器有问题,因为委托方法或 ClassB 的 PressedButtonForMethodA()
(ClassB.PressedButtonForMethodA() 仅用于调试目的)都没有被执行。使用 Swift 3 且没有故事板。这是我在 swift 操场上拥有的东西:
import UIKit
import PlaygroundSupport
class classA: UIViewController, ClassBDelegate {
private func setNavbarButtons() {
let myBarButton = classB()
myBarButton.delegate = self
let myBarButtonItem = myBarButton.setup("Press This", #selector(PressedButtonForMethodA))
self.navigationItem.rightBarButtonItem = myBarButtonItem
}
func PressedButtonForMethodA() {
NSLog("Method A in Class A fired!") // <<--THIS METHOD NOT BEING CALLED
}
}
protocol ClassBDelegate {
func PressedButtonForMethodA()
}
class classB: UIView {
var delegate: ClassBDelegate?
func setup(_ title: String, _ selectorAction: Selector) -> UIBarButtonItem {
let shadow = NSShadow()
shadow.shadowColor = UIColor.clear
let attributesNormal = [
NSForegroundColorAttributeName : UIColor.white,
NSShadowAttributeName : shadow,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 12.0)
]
let button = UIButton(type: .custom)
let buttonTitleAttributesNormal = NSAttributedString(string: title,
attributes: attributesNormal)
button.setAttributedTitle(buttonTitleAttributesNormal, for: UIControlState.normal)
let buttonTextSize = button.intrinsicContentSize
button.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width, height: buttonTextSize.height)
button.addTarget(self, action: selectorAction, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
return barButtonItem
}
func PressedButtonForMethodA() {
NSLog("Method A in Class B fired!") // <<-- THIS METHOD NOT FIRED EITHER
delegate?.PressedButtonForMethodA()
}
}
let myBarButtonItem = myBarButton.setup("Press This", #selector(PressedButtonForMethodA))
应该是
let myBarButtonItem = myBarButton.setup("Press This", #selector(myBarButton.PressedButtonForMethodA))
在设置方法中,当您应该从 ClassB 传递选择器时,您从 ClassA 传递选择器,因为您在此处添加了 self
作为目标:
button.addTarget(self, action: selectorAction, for: .touchUpInside)
完成编辑:
我对此进行了更多思考,并尝试了几种实现方式,并提出了两个合理的选择。不确定这两种方法是否会被考虑 "better," 但我想我会倾向于方法 #1。我认为它更 self-contained,并且不需要 Delegate 符合。 (忽略我的另一个答案,如果你看到它......我将两者合二为一)。
方法一
classB 是 UIBarButtonItem 的子类。调用 setup() 传递标题、Selector/Action(self 中的函数)和对 self 的引用(将用作按钮操作的目标)。
class ClassAB: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setNavbarButtons()
}
private func setNavbarButtons() {
let myBarButton = classB()
myBarButton.setup("Press Me AB", #selector(ClassAB.PressedButtonForMethodAB), self)
self.navigationItem.rightBarButtonItem = myBarButton
}
func PressedButtonForMethodAB() {
NSLog("Method AB in Class AB fired!")
}
}
class classB: UIBarButtonItem {
func setup(_ title: String, _ selectorAction: Selector, _ target: Any) {
let shadow = NSShadow()
shadow.shadowColor = UIColor.clear
let attributesNormal = [
NSForegroundColorAttributeName : UIColor.white,
NSShadowAttributeName : shadow,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 12.0)
]
let button = UIButton(type: .custom)
let buttonTitleAttributesNormal = NSAttributedString(string: title, attributes: attributesNormal)
button.setAttributedTitle(buttonTitleAttributesNormal, for: UIControlState.normal)
let buttonTextSize = button.intrinsicContentSize
button.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width, height: buttonTextSize.height)
// my navbar is white...
button.backgroundColor = UIColor.blue
// target and action both assigned by the creator (in this case, ClassAB)
button.addTarget(target, action: selectorAction, for: .touchUpInside)
customView = button
}
}
方法#2
classC 是 UIBarButtonItem 的子类。调用 setup() 传递标题,并将 self 指定为 classC 的委托。在 classC 内部,按钮 Action 是一个 class-level func,它依次调用定义的委托函数。
class ClassAC: UIViewController, ClassCDelegate {
override func viewDidLoad() {
super.viewDidLoad()
setNavbarButtons()
}
private func setNavbarButtons() {
let myBarButton = classC()
myBarButton.setup("Press Me AC")
myBarButton.delegate = self
self.navigationItem.rightBarButtonItem = myBarButton
}
func PressedButtonForMethodAC() {
NSLog("Method AC in Class AC fired!")
}
}
protocol ClassCDelegate {
func PressedButtonForMethodAC()
}
class classC: UIBarButtonItem {
var delegate: ClassCDelegate?
func setup(_ title: String) {
let shadow = NSShadow()
shadow.shadowColor = UIColor.clear
let attributesNormal = [
NSForegroundColorAttributeName : UIColor.white,
NSShadowAttributeName : shadow,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 12.0)
]
let button = UIButton(type: .custom)
let buttonTitleAttributesNormal = NSAttributedString(string: title, attributes: attributesNormal)
button.setAttributedTitle(buttonTitleAttributesNormal, for: UIControlState.normal)
let buttonTextSize = button.intrinsicContentSize
button.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width, height: buttonTextSize.height)
// my navbar is white...
button.backgroundColor = UIColor.blue
// target is self, selector action is inside self... *that* is where we'll call back to the delegate
button.addTarget(self, action: #selector(classC.classCTap), for: .touchUpInside)
customView = button
}
func classCTap() {
NSLog("tap inside ClassC ... call back to delegate method")
delegate?.PressedButtonForMethodAC()
}
}