本文介绍了在不会导致内存泄漏的情况下在代码中保留循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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 持有自己.因此,当 ViewController 在 5 秒后要求 dealloc A 时,class A 会在 deallocating 之前坚持完成循环本身.下面是输出.

If we see the code above, there is a retain cycle since class A is holding on to databaseQueue and databaseQueue is holding on to self. Thus, when ViewController asks to dealloc A after 5 seconds, class A holds on to finish the loop before deallocating itself. Below is the output.

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 以确保根本没有保留循环?

My question is this: We've a retain cycle in the code, however, this does not cause memory leak. Is it okay, in such scenarios, to leave the code as is [because it does not cause memory leak for sure]? or should I use __weak weakSelf = self and then weakSelf in the block to ensure there is no retain cycle at all?

推荐答案

你问:

这样好吗?

很大程度上,是的.

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

More accurately, it depends upon your needs/intent. If you need this to continue to run for your app to function properly (e.g. maybe you're converting and saving some images), then you definitely want a strong reference so that it finishes).

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

But if you don't need to continue to execute, then you'd use weakSelf pattern. For example, imagine you had a series of dispatched tasks in a view controller that were there solely to later trigger UI updates. In that case, if the view controller was dismissed, you might not need these blocks to run, and you certainly wouldn't want it to hang on to the view controller for a view that was long since dismissed. (You might even want to cancel those dispatched items when the view controller was dismissed, but that's another topic.)

归根结底,这取决于您的意图.

Bottom line, it depends upon your intent.

这篇关于在不会导致内存泄漏的情况下在代码中保留循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 13:23