【问题标题】:having retain cycles in code when its not causing memory leak在不导致内存泄漏的情况下在代码中保留循环
【发布时间】:2017-09-14 09:05:29
【问题描述】:
#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 一直在持有databaseQueue,而databaseQueue 一直在持有self。因此,当 ViewController 在 5 秒后请求 dealloc A 时,class 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 然后weakSelf 以确保根本没有保留周期?

【问题讨论】:

    标签: ios objective-c xcode


    【解决方案1】:

    你问:

    这样好吗?

    基本上是的。

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

    但如果您不需要继续执行,那么您将使用weakSelf 模式。例如,假设您在视图控制器中有一系列已调度的任务,这些任务仅用于稍后触发 UI 更新。在这种情况下,如果视图控制器被解除,您可能不需要这些块来运行,并且您当然不希望它挂在视图控制器上以获取早已被解除的视图。 (您甚至可能希望在关闭视图控制器时取消那些已分派的项目,但这是另一个主题。)

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

    【讨论】:

      【解决方案2】:

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

      这是一篇精彩的文章,解释了不同类型的保留周期并避免它们。

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

      【讨论】:

      • 感谢您的链接。很有见地。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多