在不引起内存泄漏的情况下在代码中保留循环

#import "ViewController.h" @implementation A - (instancetype)init { self = [super init]; if (self) { self.databaseQueue = dispatch_queue_create("someQueue", DISPATCH_QUEUE_SERIAL); } return self; } - (void) privateLogMethod { NSLog(@"private log method called"); [NSThread sleepForTimeInterval:1]; } - (void) performSomeAction { for (NSInteger i = 0; i < 10; i++) { dispatch_async(_databaseQueue, ^{ NSLog(@"inside for loop"); [self privateLogMethod]; }); } } - (void) dealloc { NSLog(@"removing A from memory"); } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.someClassA = [[A alloc] init]; [self.someClassA performSomeAction]; [self performSelector:@selector(removeA) withObject:nil afterDelay:5]; } - (void) removeA { NSLog(@"call to remove A from memory"); self.someClassA = nil; } @end #import <UIKit/UIKit.h> @interface A: NSObject - (void) performSomeAction; @property (nonatomic, strong) dispatch_queue_t databaseQueue; @end @interface ViewController : UIViewController @property (nonatomic, strong) A* someClassA; @end 

如果我们看到上面的代码,就有一个保留周期,因为class A持有databaseQueuedatabaseQueue持有self 。 因此,当ViewController在5秒钟之后要求deallocating class Aclass A继续在deallocating自己之前完成循环。 以下是输出。

 2017-09-14 14:21:06.774517+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:06.774768+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:07.775218+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:07.775480+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:08.778805+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:08.779251+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:09.784467+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:09.785089+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:10.790469+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:10.790929+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:11.775522+0530 testdealloc[72021:1812575] **call to remove A from memory** 2017-09-14 14:21:11.796196+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:11.796659+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:12.802018+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:12.802483+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:13.804953+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:13.805432+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:14.806252+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:14.806604+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:15.807852+0530 testdealloc[72021:1812626] inside for loop 2017-09-14 14:21:15.808306+0530 testdealloc[72021:1812626] private log method called 2017-09-14 14:21:16.809550+0530 testdealloc[72021:1812626] **removing A from memory** 

我的问题是这样的:我们在代码中有一个保留循环,但是,这不会导致内存泄漏。 可以,在这种情况下,保持原样[因为它确实不会导致内存泄漏]? 或者我应该使用__weak weakSelf = self ,然后使用__weak weakSelf = self来确保没有保留周期?

你问:

这个可以吗?

很大程度上,是的。

更准确地说,这取决于你的需求/意图。 如果你需要这个继续运行你的应用程序正常运行(例如,也许你正在转换和保存一些图像),那么你一定要一个强大的参考,以便它完成)。

但是如果你不需要继续执行,那么你会使用weakSelf模式。 例如,假设你在视图控制器中有一系列的调度任务,这些任务只是为了稍后触发UI更新。 在这种情况下,如果视图控制器被解散,你可能不需要这些块运行,而且你肯定不希望它挂在视图控制器上,因为这个视图已经被解散了很久。 (当视图控制器被解散时,你甚至可能想取消这些派发的项目,但这是另一个话题。)

底线,这取决于你的意图。

我第二@Rob。 但寻找任何单一的机会来避免保留周期。 对于一个简单的项目来说,这是可以的,但是在处理复杂的项目的时候…这将节省大量的时间,试图debugging/解决一个问题,如果您不确定根本原因。

这是一篇美丽的文章,解释不同types的保留周期并避免它们。

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