Swift自定义数据模型及闭包的循环引用问题

<span style="font-family: Arial, Helvetica, sans-serif;">    //在使用 KVC 的时候,如果`值没有分配空间`,</span>
    //- 如果是结构体/类,
    //会先调用默认的构造函数分配空间,然后再设置数值
    //- 如果是基本数据类型,就直接崩溃
 
    var name: String?
    var icon: String?
    var intro: String?
    var no: Int = 0
    init(dict: [String:AnyObject]) {
       super.init()
       
        // 调用 KVC 方法之前,必须调用 super.init() -> 本类的属性和父类的属性全部被初始化
        setValuesForKeysWithDictionary(dict)
    }
    
    /*
        1. setValuesForKeysWithDictionary 会遍历字典中所有的值对,依次调用 setValue
        2. 系统默认会给各个属性设置数值
        3. 如果没有key对应的属性,会调用 forUndefinedKey 方法,过滤掉不需要的属性
        4. 如果没有实现 forUndefinedKey 方法,会直接崩溃
        5. 如果父类实现了 KVC 的方法,子类就不再需要单独实现
   */
    override funcsetValue(value: AnyObject?, forKey key: String) {
       print("key-- \(key)")
       
        // 非常重要的调试技巧,有时候存在模型嵌套,需要在这里给新模型赋值,以便拿到正确的数据
       super.setValue(value,forKey: key)
    }
    
    override funcsetValue(value: AnyObject?, forUndefinedKeykey: String) {
       print("-----\(key)")
    }
//将成员变量名存到数组中
    static letproperties = ["name", "icon", "intro","no"]
//    重写description函数是为了print模型的时候方便看到模型里面的内容,这个可写可不写的
    override vardescription: String {
       let dict = dictionaryWithValuesForKeys(DWDHero.properties)
       print(dict)
       return ("\(dict)")
    }


class ViewController: UIViewController {
    
    // 记录闭包回调
    // 闭包的返回值是可选项
//    var finishedCallBack: (msg: String) -> ()?
    // 闭包是可选项 - 属性默认是强引用,控制器对闭包进行了强引用
    var finishedCallBack: ((msg: String) -> ())?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // OC 解决循环引用的方法
        // 写法 1
        // [weak self] 表示 block 中不对 self 进行强引用,self 可以随时被释放
        // 需要使用 self?.
        // weak 弱引用的对象特点:
        // 1. 不会强引用
        // 2. 指向地址的对象一旦被释放,弱引用的地址会自动设置为 nil
//        loadData { [weak self] (msg) -> () in
//            // 闭包是准备好的代码,必须要使用 self.
//            print(msg + "\(self?.view)")
//        }
        
        // 写法2
        // [unowned self]
        // 会记录 self 的地址(地址是始终存在的),但是不会做强引用
        // 风险:一旦 self 真的被释放了,程序会崩溃!
        // 特点:对象被释放,地址不改变
        loadData { [unowned self] (msg) -> () in
            // 闭包是准备好的代码,必须要使用 self.
            print(msg + "\(self.view)")
        }
    }
    
    func demoOC() {
        // __weak typeof(self) weakSelf = self
        // 弱引用的 self
        weak var weakSelf = self
        loadData { (msg) -> () in
            // 闭包是准备好的代码,必须要使用 self.
            print(msg + "\(weakSelf?.view)")
        }
    }

    /**
    加载数据
    
    目前的代码会有循环引用?
    
    问题:如果函数当前不能执行闭包,需要将闭包传递走
    1. 参数传递
    2. 使用属性记录,在需要的时候执行
    */
    func loadData(finished: (msg: String)->()) {
        
        dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
            print("耗时操作")
            
            // 主线程回调
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                // finished(msg: "hello")
                // 记录闭包
                self.finishedCallBack = finished
                
                self.working()
            })
        }
    }
    
    func working() {
        // 执行闭包 ! 表示闭包一定存在,就执行
        // unexpectedly found nil while unwrapping an Optional value
//        finishedCallBack!(msg: "hello")
        
        // 如果闭包不存在,就不执行
        finishedCallBack?(msg: "hello")
    }
    
    deinit {
        print("-----88---")
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值