ios – Swift强参考周期的令人困惑的例子

前端之家收集整理的这篇文章主要介绍了ios – Swift强参考周期的令人困惑的例子前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是 Apple’s document的一个例子:
  1. class HTMLElement {
  2.  
  3. let name: String
  4. let text: String?
  5.  
  6. lazy var asHTML: Void -> String = {
  7. if let text = self.text {
  8. return "<\(self.name)>\(text)</\(self.name)>"
  9. } else {
  10. return "<\(self.name) />"
  11. }
  12. }
  13.  
  14. init(name: String,text: String? = nil) {
  15. self.name = name
  16. self.text = text
  17. }
  18.  
  19. deinit {
  20. print("\(name) is being deinitialized")
  21. }
  22.  
  23. }

我明白为什么这个关闭属性会导致强大的参考周期,我知道如何解决它.我不会争辩这个.

真正让我感到困惑的是以下代码

  1. var heading: HTMLElement? = HTMLElement(name: "h1")
  2. let defaultText = "some default text"
  3. heading!.asHTML = {
  4. // confusing,this closure are supposed to retain heading here,but it does not
  5. return "<\(heading!.name)>\(heading!.text ?? defaultText)</\(heading!.name)>"
  6. }
  7. print(heading!.asHTML())
  8. heading = nil
  9. // 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对应的,它确实引起了我的预期的很强的参考周期.

  1. typedef NSString* (^TagMaker)(void);
  2.  
  3. @interface HTMLElement : NSObject
  4.  
  5. @property (nonatomic,strong) NSString *name;
  6. @property (nonatomic,strong) NSString *text;
  7.  
  8. @property (nonatomic,strong) TagMaker asHTML;
  9.  
  10. @end
  11.  
  12. @implementation HTMLElement
  13.  
  14. - (void)dealloc {
  15. NSLog(@"%@",[NSString stringWithFormat:@"%@ is being deinitialized",self.name]);
  16. }
  17.  
  18. @end

;

  1. HTMLElement *heading = [[HTMLElement alloc] init];
  2. heading.name = @"h1";
  3. heading.text = @"some default text";
  4.  
  5. heading.asHTML = ^ {
  6. return [NSString stringWithFormat:@"<%@>%@</%@>",heading.name,heading.text,heading.name];
  7. };
  8.  
  9. NSLog(@"%@",heading.asHTML());
  10.  
  11. heading = nil;
  12. // heading has not been deinitialized here

任何提示或指导将不胜感激.

解决方法

因为在后来的情况下

快速关闭持有强烈的标题,而不是标题的实例

在一个图像中,它显示为这样

如果我们通过set heading = nil打破红线,那么引用圆就被打破了.

更新开始:

但是,如果你没有设置为零,仍然有一个引用圈,像我上面发布的图像.你可以像这样测试

  1. func testCircle(){
  2. var heading: HTMLElement? = HTMLElement(name: "h1")
  3. let defaultText = "some default text"
  4. heading.asHTML = {
  5. return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
  6. }
  7. print(heading.asHTML())
  8. }
  9. testCircle()//No dealloc message is printed

更新结束

我还写下面的测试代码来证明闭包不能强烈地引用内存中的实例

  1. var heading: HTMLElement? = HTMLElement(name: "h1")
  2. var heading2 = heading
  3. let defaultText = "some default text"
  4. heading!.asHTML = {
  5. // confusing,but it does not
  6. return "<\(heading!.name)>\(heading!.text ?? defaultText)</\(heading!.name)>"
  7. }
  8. let cloureBackup = heading!.asHTML
  9. print(heading!.asHTML())
  10.  
  11. heading = HTMLElement(name: "h2")
  12.  
  13. print(cloureBackup())//<h2>some default text</h2>

所以,测试代码的形象是

你会从操场看到日志

  1. <h1>some default text</h1>
  2. <h2>some default text</h2>

没有找到任何关于这个的文件,只是从我的测试和理解,希望这将是有益的

猜你在找的iOS相关文章