这是
Apple’s document的一个例子:
- class HTMLElement {
- let name: String
- let text: String?
- lazy var asHTML: Void -> String = {
- if let text = self.text {
- return "<\(self.name)>\(text)</\(self.name)>"
- } else {
- return "<\(self.name) />"
- }
- }
- init(name: String,text: String? = nil) {
- self.name = name
- self.text = text
- }
- deinit {
- print("\(name) is being deinitialized")
- }
- }
我明白为什么这个关闭属性会导致强大的参考周期,我知道如何解决它.我不会争辩这个.
真正让我感到困惑的是以下代码:
- var heading: HTMLElement? = HTMLElement(name: "h1")
- let defaultText = "some default text"
- heading!.asHTML = {
- // confusing,this closure are supposed to retain heading here,but it does not
- return "<\(heading!.name)>\(heading!.text ?? defaultText)</\(heading!.name)>"
- }
- print(heading!.asHTML())
- heading = nil
- // we can see the deinialization message here,// it turns out that there is not any strong reference cycle in this snippet.
据我所知,从Swift documentation和我自己的Objective-c经验来看,变量标题将被关闭所捕获,因此应该引起很强的参考周期.但是没有,这真的让我感到困惑.
我也写了一个这个例子的Objective-C对应的,它确实引起了我的预期的很强的参考周期.
- typedef NSString* (^TagMaker)(void);
- @interface HTMLElement : NSObject
- @property (nonatomic,strong) NSString *name;
- @property (nonatomic,strong) NSString *text;
- @property (nonatomic,strong) TagMaker asHTML;
- @end
- @implementation HTMLElement
- - (void)dealloc {
- NSLog(@"%@",[NSString stringWithFormat:@"%@ is being deinitialized",self.name]);
- }
- @end
;
- HTMLElement *heading = [[HTMLElement alloc] init];
- heading.name = @"h1";
- heading.text = @"some default text";
- heading.asHTML = ^ {
- return [NSString stringWithFormat:@"<%@>%@</%@>",heading.name,heading.text,heading.name];
- };
- NSLog(@"%@",heading.asHTML());
- heading = nil;
- // heading has not been deinitialized here
任何提示或指导将不胜感激.
解决方法
因为在后来的情况下
在一个图像中,它显示为这样
如果我们通过set heading = nil打破红线,那么引用圆就被打破了.
更新开始:
但是,如果你没有设置为零,仍然有一个引用圈,像我上面发布的图像.你可以像这样测试
- func testCircle(){
- var heading: HTMLElement? = HTMLElement(name: "h1")
- let defaultText = "some default text"
- heading.asHTML = {
- return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
- }
- print(heading.asHTML())
- }
- testCircle()//No dealloc message is printed
更新结束
我还写下面的测试代码来证明闭包不能强烈地引用内存中的实例
- var heading: HTMLElement? = HTMLElement(name: "h1")
- var heading2 = heading
- let defaultText = "some default text"
- heading!.asHTML = {
- // confusing,but it does not
- return "<\(heading!.name)>\(heading!.text ?? defaultText)</\(heading!.name)>"
- }
- let cloureBackup = heading!.asHTML
- print(heading!.asHTML())
- heading = HTMLElement(name: "h2")
- print(cloureBackup())//<h2>some default text</h2>
所以,测试代码的形象是
你会从操场看到日志
- <h1>some default text</h1>
- <h2>some default text</h2>
没有找到任何关于这个的文件,只是从我的测试和理解,希望这将是有益的