委托方法不是由选择器触发的

时间:2017-03-21 20:11:53

标签: ios swift3 delegates protocols selector

我将A类中的选择器传递给B类中的方法,最终从A类触发委托方法PressedButtonForMethodA。但是,我认为我的选择器出了问题,因为代理人都没有方法或ClassB的PressedButtonForMethodA()(ClassB.PressedButtonForMethodA()仅用于调试目的)正在执行。使用Swift 3和NO故事板。这就是我在快捷的游乐场里所拥有的:

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()
    }
}

2 个答案:

答案 0 :(得分:2)

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)

答案 1 :(得分:2)

完成编辑:

我对此有了更多的考虑,并且通过几种方式进行了解决,并提出了两个合理的选择。不确定这两种方法是否会被认为是“更好”,但我想我会倾向于方法#1。我认为它更加独立,并且不需要委托符合。 (忽略我的另一个答案,如果你已经看到了......我将两者合二为一。)

方法#1

classB是一个UIBarButtonItem子类。调用setup()传递标题,Selector / Action(自我内部的一个函数)和一个对self的引用(它将用作按钮Action的目标)。

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 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()
    }

}