美文网首页
一些小东西

一些小东西

作者: 忧郁的小码仔 | 来源:发表于2019-05-23 10:54 被阅读0次
1. swift中的数组等导致的循环引用
class Person {
  // ...
  var friends: [Person] = []
  // ...
}

      let person1 = Person()
      let person2 = Person()
      
      person1.friends.append(person2)
      person2.friends.append(person1)

像上面这样,由于Person对象强引用着friends数组,同时,它里面包含的对象又是Person址类型,从而产生了循环引用,导致person1和person2都不能释放。你可能想使用unowned或者weak。但是unowned和weak只能用来修饰class类型,而friends是struct类型。所以,这种情况下,只能将friends数组里的元素包装一下,变成unowned或者weak。像下面这样就可以了:

class Unowned<T: AnyObject> {
  unowned var value: T
  init(_ value: T) {
    self.value = value
  }
}

class Person {
   // ...
  var friends: [Unowned<Person>] = []
   // ...
}

      let person1 = Person()
      let person2 = Person()
      
      person1.friends.append(Unowned(person2))
      person2.friends.append(Unowned(person1))

这样,加入到friends数组里的person1和person2就都变成unowned类型了。

2. Xcode中的 Debug Memory Graph工具检测循环引用

将app运行起来以后,将有问题的部分跑一边,然后点击下图中红色部分的按钮:

1.png

在下图中,左边红色框中,只要用这种紫色框加白色感叹号标注的对象就是产生问题的对象,选中该对象后,右边(红框中)就会展示对象间的引用关系,比如下面这种循环引用:

2.png
3. swift closure循环引用问题

先看个两个小例子:

class Person {
  let firstName: String
  let lastName: String

  lazy var fullName: () -> String = { 
    self.firstName + " " + self.lastName
  }
   // ...
}

let john = Person(firstName: "A", lastName: "B")
print(john.fullName())

这里,由于closure捕获了当前实例,同时,当前实例又强引用着fullName这个closure,所以导致john对象一直不能释放。

var x = 5
 var y = 5
    
    let someClosure = { [x] in
      print("\(x), \(y)")
    }
    x = 6
    y = 6
    
    someClosure()        // Prints 5, 6
    print("\(x), \(y)")  // Prints 6, 6

在上面这个小例子中,由于x在someClosure这个closure的capture list中,所以在定义这个closure的时候,就会捕获x的拷贝。而y不在capture list中,closure只能捕获他的引用,这意味着只有在closure运行的时候才能知道y的值,而不是在捕获的时候。

capture list的这个特性使得我们给closure中使用的对象添加unowned,weak成为可能,比如,上面fullName closure这个例子中,就可以像下面这样来打破引用循环:

class Person {
  let firstName: String
  let lastName: String

  lazy var fullName: () -> String = { [unowned self] in
    self.firstName + " " + self.lastName
  }
   // ...
}

这里,我们在capture list中使用unowend或者weak 来捕获self, 这样就不存在强引用的问题了。上面这种捕获的写法是一种简写,全写应该是像这样的:

  lazy var fullName: () -> String = { [unowned unownedSelf = self] in
    unownedSelf.firstName + " " + unownedSelf.lastName
  }

这里要千万注意unowned和weak的选择。weak修饰的是optional类型,如果对象销毁了,它修饰的变量就会变成nil;而unowned则不同,它修饰的不是optional类型,如果去访问一个已经销毁的对象,就会触发运行时错误,所以使用unowned一定要保证使用的时候对象是存在的。

相关文章

  • 一些小东西

    (一) 闲日子一多 就开始乱想 想起一片田野 风吹绿草 麻雀低飞 旧草屋里升起袅袅的烟 我们站在楼顶 你指着夕阳的...

  • 一些小东西

    coding 的主页 配置SSH公钥 当公司需要对管理的项目代码保密的时候,总是会对访问和修改的人设置权限,及配备...

  • 一些小东西

  • 一些小东西

    1. swift中的数组等导致的循环引用 像上面这样,由于Person对象强引用着friends数组,同时,它里面...

  • 一些小东西

    其实谈不上什么朋友吧 有时候觉得是这样的 其实也谈不上很喜欢吧 有时候觉得也是这样 其实只是太懦弱了吧 有时候他们...

  • 一些小东西

    躺着包着黑的杂货箱, 头顶还是凌晨的三四点的点点星光 肾上腺素搅浑了脑子里沉重的脑浆 咳嗽着肺里38度的霉, 清晨...

  • NO.19稳稳21天简笔画练习

    花一些零碎时间,画一些小东西

  • 橡皮章

    都是前段时间做的一些小东西

  • 2018-07-08

    所有的一些小东西都将汇成大海

  • 一些小东西笔记

    1.glide能直接模糊加载回来的图片 2.android分进程能保证能防止一些意外的APP崩溃. android...

网友评论

      本文标题:一些小东西

      本文链接:https://www.haomeiwen.com/subject/hlqvzqtx.html