在函数中创建的对象尽管经过了进一步的传递仍会消失

问题描述 投票:0回答:1

来自另一种语言,我对一个无声的错误感到惊讶,该错误中从未调用过作为回调传递给方法的对象。对回调的引用以某种方式丢失了。

问题的最小(不可运行)示例:

class Foo: NSObject, AVCaptureFileOutputRecordingDelegate {
    func bar() {
        let out = AVCaptureMovieFileOutput()
        let delegate = Foo() //nonsensical in this case, in normal case diff. object will be used
        out.startRecording(to: /*...*/, recordingDelegate: delegate)

        //Result: delegate methods are never called
    }
}

“解决方案”的最小示例(不可运行):

class Foo: NSObject, AVCaptureFileOutputRecordingDelegate {
    func bar() {
        let out = AVCaptureMovieFileOutput()
        out.startRecording(to: /*...*/, recordingDelegate: self)

        //Result: delegate methods are called when approperiate
    }
}

我很困惑...

  • 为什么会这样?
  • 如何防止这种情况?
  • 这种无意的失败是设计使然吗?

此问题源自AVCaptureMovieFileOutput never calls delegate on screen recording

swift syntax garbage-collection
1个回答
0
投票

大多数委托是weak,因此它们不会创建保留周期,请参阅Automatic Reference Counting (ARC)。大多数情况是假设您正在使用的代理存储为weak

在您的第一个示例中,对对象的唯一强引用由函数bar保留,因为委托是弱引用。函数结束后,仅剩下的强引用将消失,该对象可以自由删除。

class Foo: NSObject, AVCaptureFileOutputRecordingDelegate {
    func bar() {
        let out = AVCaptureMovieFileOutput()
        let delegate = Foo() //object created, and strong reference stored in variable called delegate
        out.startRecording(to: /*...*/, recordingDelegate: delegate) // object passed in and likely stored in a weak variable inside of the `out` object. This means it will not keep a strong reference to your Foo object.

        //Result: delegate methods are never called
    }// local variable called delegate goes out of scope, strong reference to your Foo object goes away, there are no more strong references, can be deleted.
}

在第二个示例中,当使用self作为委托人时,self可能在bar函数结束后仍然存在,因此委托仍然存在。

class Foo: NSObject, AVCaptureFileOutputRecordingDelegate {
    func bar() {
        let out = AVCaptureMovieFileOutput()
        out.startRecording(to: /*...*/, recordingDelegate: self) // pass `self`, which presumably has something else referencing it with a strong reference, so it stays alive

        //Result: delegate methods are called when approperiate
    } // `self` still has strong references to it (somewhere else) keeping it alive after the function call, so the weak reference that is being used to call the delegate methods can still operate! Yay!
}

希望能回答“为什么”。

关于预防,您需要确保牢记要保留的任何委托(或弱变量)。

此行为是设计使然,因为它用于防止保留周期和内存泄漏。在使用委托设计自己的类时,您可以根据需要适当使用weak来防止保留周期。

© www.soinside.com 2019 - 2024. All rights reserved.