类实例上的Swift协议永远不会触发

时间:2017-06-26 08:20:42

标签: swift swift-protocols

我有一个快速的协议,但它永远不会发射。

我有一个类是一个实例,另一个是我想管理对象的类;

protocol TurnDelegate: class {
    func turnIsCompleted()
}

class ClassOne : NSObject {

    weak var delegate: TurnDelegate?

    override init() {
        super.init()
        delegate?.turnIsCompleted()
    }

}

class ClassTwo: NSObject, TurnDelegate {

    static var instance = ClassTwo()

    func turnIsCompleted() {
        print ("Turn is completed")
    }

}

let c2:ClassTwo = ClassTwo.instance
let c1:ClassOne = ClassOne.init()

我的问题是协议永远不会触发,也不会输出“回合完成”

我该如何解决这个问题?

编辑:如何设置代理?

非常感谢

3 个答案:

答案 0 :(得分:2)

如果您描述了创建自定义init

class ClassOne : NSObject {

    weak var delegate: TurnDelegate?

    init(with delegate: TurnDelegate?) {
        self.delegate = delegate
        delegate?.turnIsCompleted()
    }

}

比:

let c2:ClassTwo = ClassTwo.instance
let c1:ClassOne = ClassOne.init(with: c2)

输出:

Turn is completed

答案 1 :(得分:2)

您忘记设置代理。

通常委托是用init方法设置的。稍后在另一种方法中调用协议中的方法,例如

protocol TurnDelegate: class {
    func turnIsCompleted()
}

class ClassOne : NSObject {

    weak var delegate: TurnDelegate?

    init(delegate: TurnDelegate?) {
       self.delegate = delegate
    }

    func turnSomething()
    {
        delegate?.turnIsCompleted()
    }

}

class ClassTwo: NSObject, TurnDelegate {

    static let instance = ClassTwo()

    func turnIsCompleted() {
        print ("Turn is completed")
    }

}

let c2 = ClassTwo.instance
let c1 = ClassOne(delegate: c2)
c1.turnSomething()

然而为了这个目的,特别是与单身人士一起,我更喜欢回调闭包而不是协议/委托。优点是开销较小,回调直接连接到调用方法。

class ClassOne : NSObject {

    func turnSomething()
    {
        let c2 = ClassTwo.instance
        c2.turn { 
            print ("Turn is completed")
        }
    }
}

class ClassTwo: NSObject {

    static let instance = ClassTwo()

    func turn(completion: ()->()) {
        // do heavy work
        completion()
    }

}

let c1 = ClassOne()
c1.turnSomething()

答案 2 :(得分:1)

代表们的所有荣耀也有其缺点。其中之一是必须明确建立对象与其代理之间的关系。在Cocoa中,通常有两种方法可以做到这一点。一个是在InterfaceBuilder中连接delegate IBOutlet,另一个是以编程方式进行连接。正如@OlegGordiichuck指出你可以在初始化器中完成它,但通常在Cocoa委托中往往是属性。在您的情况下,这将归结为实例化ClassTwoClassOne的对象,然后手动设置c2的委托,如

c2.delegate = c1

然而,这会破坏您的通知机制,您必须有一个单独的方法来通知代理人(这通常是典型的,因为通常您的代理人在构建期间无法知道重要的其他。发起人的建设通常不是代表必须知道的事情)。