繁体   English   中英

在Swift中使用值类型进行委派?

[英]Delegation with value types in Swift?

在我的应用程序中,我使用委托:控制器C使用委托D1和名为M1的模型项目, M1使用委托与另一个名为M2模型项目。

M1C调用委托方法时,一切都很好。

C ---> M1
<----- delegation : OK

M2M1调用委托方法时,一切都很好。

M1 ---> M2
<------ delegation : OK

但是当M2M1调用委托方法时,又从C调用委托方法,这不起作用。

C ---> M1 ---> M2
       <------ delegation
<------ delegation

调试器显示M1委托的值为nil,因为它应该是C

更新

protocol TestOneDelegate:class {

    func testMethodOne(message:String)

}

protocol TestTwoDelegate {

    func testMethodTwo(message:String)

}

//
struct M2 {

    var delegate:TestTwoDelegate?

    func testOperation() {
        delegate?.testMethodTwo(message:"From M2" )
    }
}


struct M1:TestTwoDelegate {

    weak var delegate:TestOneDelegate?
    var m2:M2

    init() {
        m2 = M2()
        m2.delegate = self
    }

    mutating func testOperation() {
        delegate?.testMethodOne(message: "From M1 - Start")

        // BREAKPOINT 1
        m2.testOperation()

        delegate?.testMethodOne(message: "From M1 - End")

    }

    /// Implementation of TestTwoDelegate
    func testMethodTwo(message:String) {

        // BREAKPOINT 2
        print ("M1 get message from M2: " + message)
        delegate?.testMethodOne(message: message + " via M1")
    }

}


class TestControler:UIViewController,TestOneDelegate {

    var m1:M1!

    required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

        m1 = M1()
        m1.delegate = self
        m1.testOperation()
    }

    /// Implementation of TestOneDelegate
    func testMethodOne(message:String) {
        print ("Controller get following message from M1: " + message)
    }


}

预期成绩:

Controller get following message from M1: From M1 - Start
M1 get message from M2: From M2
Controller get following message from M1: From M2 via M1  
Controller get following message from M1: From M1 - End

获得的结果:

Controller get following message from M1: From M1 - Start
M1 get message from M2: From M2
Controller get following message from M1: From M1 - End

From M2 via M1失踪...

停在'BREAKPOINT 1'上, delegate有一个值。
停在'BREAKPOINT 2'上, delegate是零。

我错过了什么吗?

答案是由@OOper给出的

使用值类型赋值创建实例的副本。 所以在M1.init()m2.delegate = self创建实例的副本,然后将其分配给m2.delegate 因此,对M1实例所做的任何修改都不会反映到m2.delegatem2.delegate也是nil

Swift编程语言的 类和结构相关的部分引用:

作为一般准则,考虑在以下一个或多个条件适用时创建结构:
...
- 结构存储的任何属性本身都是值类型,也可以复制而不是引用它们。

所以这个问题的最佳答案是在需要委托时使用class而不是struct

出于好奇心的目的,下面是对仍然使用struct的初始问题的两个答案。 请注意,这些解决方案仅适用于此示例的范围。 如果m1控制器访问属性可能会出现问题。

假设testMethodTwo现在修改m1属性:

func testMethodTwo(message:String) {

    // Properties are modify here
    // BREAKPOINT 2
    print ("M1 get message from M2: " + message)
    delegate?.testMethodOne(message: message + " via M1")
}

然后,当它的方法testMethodOne是调用控制器将不会看到这些修改m1 ,因为它们发生在一个独特的副本m1

1.使用代理进行初始化

struct M1:TestTwoDelegate {

    var m2 = M2()
    weak var delegate:TestOneDelegate?


    init(delegate:TestOneDelegate) {
        self.delegate = delegate
        m2.delegate = self
    }

2.传播更新

struct M1:TestTwoDelegate {

    var m2 = M2()

    weak var delegate:TestOneDelegate? {
        didSet {
            m2.delegate = self
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM