避免使用ARC(强引用/弱引用)产生循环保留,学习一些基础知识。

4

目前我似乎还没有遇到问题,但我想确保我正在使用一些最佳实践。

假设我有一个UITableViewController,其数据源是MyObject对象的NSArray。那么在我的UITableViewController中,我会这样声明我的数据源:

@property (strong, nonatomic) NSArray *dataSource;

当我点击一个单元格后,希望能够推出一个新的视图,显示该单元格对应的MyObject的详细信息。因此,在新的UIViewController中,我有以下代码:

@property (strong, nonatomic) MyObject *myObject;

现在,在UITableViewController中当一个单元格被点击时:

MyObject *myObject = [[self dataSource] objectForIndex:[indexPath row]];
NewView *view = [[NewView alloc] initWithMyObject:myObject];
// ... push onto nav controller, etc

基本上我担心的是我的数组被声明为strong,详细视图中的MyObject被声明为strong,谁知道可能有另一个视图也用了相同被声明为strong的MyObject。

总之:这是在视图间传递对象的正确方式吗?我还没有在我的应用中使用弱引用,感觉这不太对。任何帮助或链接都将是惊人的。

2个回答

4

这不是循环引用。这是一种很好的做法。 MyObject 的实例不会强烈引用任何其所有者,因此当它们中的最后一个拥有者最终被释放时, 该对象也会被释放。


4
好的。数组加1,当详细视图控制器被推送时,myObject加2,然后在弹出并最终释放时再加1。如果您从数组中删除myObject,它的保留计数会变为0。如果持有数组的视图控制器被释放,该数组也将被释放,并释放其内容。这正是您想要的。 - danh
记录保留计数会得到加分(无任何双关语)。我曾考虑过此事,但太懒了没去做。 - warrenm

4
我觉得你需要了解的是arc的工作原理。 强引用所指向的对象会被保留,这是基本的工作原理。
它通过在对象中添加引用计数器来实现。当你进行如下操作时:
```swift var object = Object() ```
对象的引用计数器会增加1。
当没有强引用再指向对象时,引用计数器会减少1。如果引用计数器为0,对象就会被释放。
@property (strong, nonatomic) MyObject *myObject;

你需要为myObject创建一个STRONG指针(而不是对象)。
但是当你这样做时:
MyObject *myObject = [[self dataSource] objectForIndex:[indexPath row]];

使此指针增加数据源中指定索引处的任何内容的引用计数。

重要的是只要指针继续指向此对象,它就会被保持活动状态。

关于你对视图的担忧。

在界面构建器中创建的视图使用强指针在内部声明其元素。这是当你想要使用引用时的情况。当你在视图中添加自己的IBOutlet元素时,最好将其设置为弱引用。从逻辑上考虑原因,这基本上意味着你不关心此界面构建器元素,因为你只希望它在视图控制器被释放之前存活。

通常遇到保留周期的情况是对象具有子对象,并且该子对象具有指向其父对象的引用。

这是:

对象A使用指针创建对象B

对象B使用指针指向对象A

A将使B保持活动状态,B将使A保持活动状态。

此页面将向您解释有关如何避免此类问题的一些基本信息:

http://cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html

另外,关于在视图之间传递对象,这非常简单。

首先从View 1获取到指向View 2的指针(可以是强引用或弱引用,取决于谁应该保持View 2保持活动状态,如果是来自IB Builder,则应为弱引用,如果是程序化,则应为强引用)

其次,在View 2中创建一个属性(@property (strong, nonatomic) MyObject *myObject;)

现在就这么简单:

Self.view1Pointer.myObject = self.myOtherObject;

了解这里,两个视图都强烈指向这个对象,所以只要其中一个视图没有被释放,该对象就会被保留。
你不会创建保留循环,你只是将该对象的引用计数设置为2。
注意:当视图被释放时,它的所有指针都设置为nil,因此任何被它们指向的对象的引用计数都会减少。如果达到0,则会被释放。(在前面的情况下,myobject的值仍为1,因为另一个视图仍然指向它)。
唯一可能创建保留循环的场景是如果你成功使myObject也强烈指向View2。现在它们互相保持活动状态。(但正如之前所述,你可以使myObject 弱引用view2,这不会创建保留循环)。
你可以在这里了解更多关于 arc 的知识:http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1

惊人的答案。我正在教几个朋友如何做简单的iOS开发,但在我误导他人之前,我需要理解核心内存系统。 - rnystrom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接