Swift3,你必须把这个弱变量框起来,对吗?

Swift3,你必须把这个弱变量框起来,对吗?,swift3,weak-references,boxing,Swift3,Weak References,Boxing,我有四个关于装箱弱引用的常见过程的模糊问题 为了演示这些问题,这里有一个通知系统,Notes 你会像这样使用它 class SyncedCell: UITableViewCell, Notes { override func layoutSubviews() { ... listen(forNote: "soloCell") } func editing() { say(note: "soloCell")

我有四个关于装箱弱引用的常见过程的模糊问题

为了演示这些问题,这里有一个通知系统,
Notes

你会像这样使用它

class SyncedCell: UITableViewCell, Notes {

    override func layoutSubviews() {
        ...
        listen(forNote: "soloCell")
    }
    func editing() {
        say(note: "soloCell")
        ...
        input.becomeFirstResponder()
    }
    func note() {
        print("Hooray, I got a note..")
        editingCancel()
    }
因此,
Notes
的代码如下

对于一个给定的键(比如“soloCell”),您只需保留一个数组,该数组包含对调用该键时希望获取消息的任何对象的引用

当然,这些必须是弱引用

所以,当一个新的对象到达,需要在列表中记忆

    var b:_Box = _Box()
    b.p = self
    _notes[k]?.append(b)
(函数“listen”只是将该对象添加到该键的项列表中。“say”函数会遍历该键的侦听项列表:对于每个项,如果该项在此期间没有消失,则会发送一条消息。)

所以!据我所知,您不能保留弱引用数组

你必须把它们包装起来,正如你在下面的kodes中看到的那样

  • 真的,对吗?使用框很难看,有没有办法只保留一个弱引用列表?不用打拳击

  • 相关:在kodes
    中,任何对象都是基础。那是最好的吗

  • 请注意,协议不是
    :class
    。这是令人不安的,我不确定是否应该

  • 请注意,非常不幸的是,就我所知,在Swift中,无法观察到弱引用变为零。截至2017年,情况是否仍然如此?有什么办法可以做到这一点吗

  • 脚注-关于第4点,“有没有办法实现这一点?”唯一的可能性似乎是在关注的项目中添加一个关联的主题。(例如)[

    代码

    struct _Box {
        weak var p: AnyObject?
        // note: I prefer to spell out the assigment,
        // rather than have a convenience initializer here
    }
    
    var _notes:[String:[_Box]] = [:]
    
    protocol Notes {
        func note()
    }
    
    extension Notes where Self:AnyObject {
    
    func listen(forNote k: String) {
        if _notes.index(forKey: k) == nil {
            _notes[k] = []
        }
        var b:_Box = _Box()
        b.p = self
        _notes[k]?.append(b)
    }
    
    func say(note k:String) {
        if let _n = _notes[k] {
            var k:Int = 0
            print("notes.4            saying......")
            for b in _n {
                let p = b.p
                if (p == nil) {
                    print("\(k) notes.4            there's one that's been removed")
                }
                else {
                    print("\(k) notes.4            sending ok...")
                    (p as! Notes).note()
                }
                k = k + 1
            }
        }
        __noteCleaner()
    }
    
    func __noteCleaner() {
        for var (k, _n) in _notes {
            let kn = _n.count
            for i in (0..<kn).reversed() {
                let p = _n[i].p
                if (p == nil) {
                    _n.remove(at: i)
                    let newk = _n.count
                    print("notes.4, removed a dud listener for key \(k) new length is \(newk)")
                }
            }
            if (_n.count == 0) {
                print("notes.4, removed a seemingly unused key \(k)")
                _notes.removeValue(forKey: k)
            }
        }
    }
    
    struct\u框{
    弱var p:任何对象?
    //注:我更愿意详细说明分配,
    //而不是在这里有一个方便的初始值设定项
    }
    变量注释:[字符串:[[u框]]=[:]
    协议说明{
    func note()
    }
    扩展注释,其中Self:AnyObject{
    func listen(forNote k:String){
    如果注释索引(forKey:k)=nil{
    _注释[k]=[]
    }
    变量b:_-Box=_-Box()
    b、 p=自我
    _注[k]?.追加(b)
    }
    func say(注k:字符串){
    如果让_n=_注释[k]{
    变量k:Int=0
    打印(“注释4表示……”)
    对于b in n{
    设p=b.p
    如果(p==nil){
    打印(“\(k)注释。4有一个已删除”)
    }
    否则{
    打印(“\(k)注释。4发送确定…”)
    (p as!Notes)
    }
    k=k+1
    }
    }
    __noteCleaner()
    }
    func _unoteCleaner(){
    对于票据中的var(k,_n){
    让kn=计数
    
    因为在(0..中,我将专注于问题的核心

    您正试图通过注册主体上的观察者来实现观察者(侦听器)模式。我猜主体将手动调用每个观察者

    有一种更简单的方法来实现这一点。你可以使用单例。观察者将在单例上注册,当发生重要的事情时,主体将通知单例

    这有一个特殊的类,
    NotificationCenter
    。它只保留无主引用

    代表不是为一个观察者制作的,也不是为多个观察者制作的

    当然,有一种简单的方法可以通过将引用包装到结构/对象中来实现弱引用数组,请参见

    然而,我认为您的问题是由您的体系结构引起的。您将视图类与模型类混合在一起,这不是一个好主意

    具体回答您的问题:

  • 不。我相信Swift邮件列表中关于这一点的讨论以“您可以包装它”结束。您不必如此简单地包装它。您可以编写自己的数组版本,在内部进行包装

  • 使用泛型而不是
    AnyObject
    ,请参见上面的链接问题

  • 是的,这是令人不安的。这是可能的,因为您实际上只在
    任何对象
    (即类)上使用它,并且您正在删除
    中的类型。使用
    框。p
    声明为
    注释
    这将不起作用,除非
    注释
    协议

  • 这是正确的。请参阅。一个简单的解决方法是在释放侦听器时手动删除侦听器(在
    deinit


  • 相关:你也可以使用函数currying来保留弱引用。我基于此编写了一个事件通知系统。@benzi,谢谢,这需要一些思考。也许有一天你可以在这里用一句话给出一个非常简短的答案。我将再次回顾你的文章,谢谢。嗨,Sulthan!正如你所说,(1)它是一个单例。(_notes是一个全局的-本质上是一个单例)。正如你所说(2)观察者在单例中注册(注意
    listen#
    在顶部的示例代码中)(3)当发生某件事时会通知单例(注意
    say#
    在顶部的示例中).继续,你提到了
    NSNotificationCenter
    -这真是一派胡言;我从未加入过使用它的团队。在Swift时代,人们基本上可以说“永远不要使用它”。下一步:)您提到存储弱引用数组的一种常见方法是将它们装箱。这是真的;我在这里给出的示例代码中给出了一个极好的、完美的例子。关于上述常见技术,我有四个具体的、详细的问题-参见1到4!最后Sulthan!:)您提到了一个“问题”在最后一段中,您提到了MVC。我不确定您的意思:我给出的通知用法示例是,当您同步单元格时。这是唯一的方法