zoukankan      html  css  js  c++  java
  • iOS循环引用

    iOS循环引用

    • 当前类的闭包/Block属性,用到了当前类,就会造成循环引用

      1. 此闭包/Block应该是当前类的属性,我们经常对Block进行copy,copy到堆中,以便后用。
      2. 单方向引用是不会产生循环引用。需要self引用闭包/Block,Block中使用self。
    • 有两个规则:

      1. 如果你是通过引用来访问一个实例变量,那么将强引用至self。
      2. 如果你是通过值来访问一个实例变量,那么将直接强引用至这个“值”变量。

    Object-C Block循环引用情况

    • 一般来说我们总会在设置Block之后,在合适的时间回调Block,而不希望回调Block的时候Block已经被释放了,所以我们需要对Block进行copy,copy到堆中,以便后用。
    • 当一个Block被Copy的时候,如果你在Block里进行了一些调用,那么将会有一个强引用指向这些调用方法的调用者。

    swift 中闭包循环引用情况

    class ViewController: UIViewController {
    	// 1.闭包是当前类属性
        var allCallBack :(()->())?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            CyclicLead {
            	// 闭包引用当前类
                print(self.view)
            }
        }
    
        // 循环引用的方法
        func CyclicLead(completionBack:@escaping ()->()) -> Void {
        	// 2.当前类引用闭包
            allCallBack = completionBack
            
            DispatchQueue.global().async {
                
                DispatchQueue.main.async {
                    completionBack()
                }
            }
        }
        
        // 当对象销毁时会调用
        deinit {
            print("销毁了")
        }
    }
    

    解除循环引用

    OC方式

    • 方式一
    __weak typeof(self) weakSelf = self;
    self.block = ^(NSString *name){
    	NSLog(@"view:%@", weakSelf.view);
    };
    
    • 方式二
    __unsafe_unretained typeof (self) weakSelf = self;
    [self loadData:^{
        NSLog(@"%@", weakSelf.view);
    }];
    

    swift方式

    • 方案一:
      • 使用weak,对当前控制器使用弱引用
        // 解决方案一:
        /*
        细节1:var	,weak 只能修饰var,不能修饰 let
         'weak' must be a mutable variable,
          because it may change at runtime
          weak 可能会被在运行时被修改 -> 指向的对象一旦被释放,会被自动设置为nil
        细节2: weakSelf?  weakSelf!	两种解包方式
        ?可选解包 - 如果self已经被释放,不会向对象发送getter消息
    		可选解包只是单纯的发送消息,没有计算
        ! 强行解包 - 如果self已经被释放,强行解包会导致崩溃
        	强行解包可以参与计算,可选项不能直接参与到计算
        */
    	weak var weakSelf = self
    	CyclicLead {
    		print(weakSelf?.view)
    	}
    
    • 方案二:
      • 和方案一类型,只是书写方式更加简单
      • 可以写在闭包中,并且在闭包中用到的self都是弱引用
    CyclicLead {[weak self]()->() in            
    	print(self?.view)
    }
    // 缩减写法
    CyclicLead {[weak self] in
    	print(self?.view)
    }
    
    • 方案三:
      • 使用关键字unowned
      • 从行为上来说 unowned 更像OC中的 unsafe_unretained
      • unowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不能是 Optional 值,也不会被指向 nil
      • [unowned self]表示 {} 中的所有 self 都是 assign 的,不会强引用,但是,如果对象释放,指针地址不会变化如果对象被释放,继续调用,就会出现野指针的问题
    CyclicLead {[unowned self]()->() in
    	print(self?.view)
    }
    
    // 缩减写法
    CyclicLead {[unowned self] in
    	print(self?.view)
    }
    
    
  • 相关阅读:
    设计模式的四个基本要素
    拖拉记录上下移动--Ajax UI
    Rails-Treasure chest2 嵌套表单;
    YAML(摘录)
    Rails-Treasure chest1 (自定义Model网址;多语言包; 时区设置, TimeZone类; 格式日期时间; 表单单选UI; 表单多选UI;Select2 Plugin)
    iTerm2的设置和Zsh.
    **优化--后端**: 计数缓存counter_cache; rack-mini-profiler(2300🌟) ; bullet(5000✨):侦测N+1query
    优化--前端(全占课,未完成作业:);CDN; Http/2的设置(未完成)
    null值的判断
    if else
  • 原文地址:https://www.cnblogs.com/ShaoYinling/p/5832882.html
Copyright © 2011-2022 走看看