首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Swift委托-何时在委托上使用弱指针

Swift委托-何时在委托上使用弱指针
EN

Stack Overflow用户
提问于 2015-05-05 22:58:34
回答 2查看 22.1K关注 0票数 43

有人能解释一下在Swift中什么时候和什么时候不使用委托指针的“弱”赋值吗?为什么?

我的理解是,如果你使用一个没有被定义为类的协议,你不能,也不想把你的委托指针赋值给弱。

代码语言:javascript
运行
复制
protocol MyStructProtocol{
    //whatever
}

struct MyStruct {
    var delegate: MyStructProtocol?
}

但是,当您的协议被定义为类类型协议时,您是否希望将委托设置为弱指针?

代码语言:javascript
运行
复制
protocol MyClassProtocol: class{
    //whatever
}

class MyClass {
    weak var delegate: MyClassProtocol?
}

我说的对吗?在Apple的快速指南中,类协议示例没有使用弱赋值,但在我的测试中,如果我的委托没有被弱引用,我就会看到强引用循环。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-06 01:13:12

您通常使用类协议weak来避免“强引用循环”(以前称为“保留循环”)的风险。(请注意,我们现在通过将AnyObject协议添加到协议的继承列表中来做到这一点;请参见Class-Only Protocols;我们不再使用class关键字。)没有将委托设为weak并不意味着你天生就有一个很强的引用循环,而仅仅意味着你可以有一个。

但是,使用struct类型,强引用周期风险大大降低,因为struct类型不是“引用”类型,因此很难创建强引用周期。但是,如果委托对象是类对象,那么您可能希望使协议成为类协议,并使其变弱。

在我看来,将类委托设为weak只是部分缓解了强引用循环的风险。这也是一个所有权问题。大多数委托协议都是这样的情况:相关对象不需要声明对代理的所有权,而只是提供通知代理某些内容(或请求某些内容)的能力。例如,如果您希望视图控制器具有一些文本字段委托方法,则文本字段无权声明视图控制器的所有权。

票数 48
EN

Stack Overflow用户

发布于 2019-10-08 04:24:29

正如Rob所说:

这实际上是一个“所有权”的问题

这是非常正确的。“强引用循环”就是为了获得正确的所有权。

在下面的示例中,我们没有使用weak var。然而,这两个对象都将解除分配。为什么?

代码语言:javascript
运行
复制
protocol UserViewDelegate: class {
    func userDidTap()
}

class Container {
    let userView = UserView()
    let delegate = Delegate()
    init() {
        userView.delegate = delegate
    }

    deinit {
        print("container deallocated")
    }
}

class UserView {
    var delegate: UserViewDelegate?

    func mockDelegatecall() {
        delegate?.userDidTap()
    }

    deinit {
        print("UserView deallocated")
    }
}

class Delegate: UserViewDelegate {
    func userDidTap() {
        print("userDidTap Delegate callback in separate delegate object")
    }
}

使用:

代码语言:javascript
运行
复制
var container: Container? = Container()
container?.userView.mockDelegatecall()
container = nil // will deallocate both objects

内存所有权图(没有循环)

代码语言:javascript
运行
复制
    +---------+container +--------+
    |                             |
    |                             |
    |                             |
    |                             |
    |                             |
    |                             |
    v                             v
userView +------------------> delegate

为了创建一个强大的参考周期,这个周期需要完成。delegate需要返回到container,但它没有,所以这不是问题。但纯粹是出于所有权的原因,正如Rob所说的那样,here

在对象层次结构中,子对象不应维护对对象的强引用。这是一个红色信号,表示强烈的参考周期。

所以不管有没有泄漏,对于你的委托对象,仍然要使用weak

在下面的示例中,我们没有使用weak var。因此,这两个类都不会解除分配。

代码语言:javascript
运行
复制
protocol UserViewDelegate: class {
    func userDidTap()
}

class Container: UserViewDelegate {
    let userView = UserView()

    init() {
        userView.delegate = self
    }

    func userDidTap() {
        print("userDidTap Delegate callback by Container itself")
    }
    deinit {
        print("container deallocated")
    }
}

class UserView {
    var delegate: UserViewDelegate?

    func mockDelegatecall() {
        delegate?.userDidTap()
    }

    deinit {
        print("UserView deallocated")
    }
}

使用:

代码语言:javascript
运行
复制
var container: Container? = Container()
container?.userView.mockDelegatecall()
container = nil // will NOT deallocate either objects

内存所有权图(有循环)

代码语言:javascript
运行
复制
     +--------------------------------------------------+
     |                                                  |
     |                                                  |
     +                                                  v
 container                                           userview
     ^                                                  |
     |                                                  |
     |                                                  |
     +------+userView.delegate = self //container+------+

使用weak var可以避免强引用循环

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30056526

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档