2017-09-14 57 views
1
#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秒後要求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以確保沒有保留週期?

回答

2

你問:

這樣行嗎?

很大一點,是的。

更準確地說,這取決於您的需求/意圖。如果您需要需要這樣才能繼續運行以使您的應用正常運行(例如,您可能正在轉換並保存一些圖像),那麼您肯定需要一個強大的引用以便完成)。

但是,如果你不需要繼續執行,那麼你會使用weakSelf模式。例如,假設您在視圖控制器中有一系列調度任務,而這些任務僅用於稍後觸發UI更新。在這種情況下,如果視圖控制器被解散,你可能不需要這些塊運行,並且你肯定不希望它掛在視圖控制器上,因爲這個視圖已經被解散了很久。 (當視圖控制器被解僱時,你甚至可能想取消那些派發的項目,但這是另一個主題。)

底線,它取決於你的意圖。

1

我第二@Rob。但尋找任何避免保留週期的機會。對於一個簡單的項目來說,這是可以的,但是在處理複雜的項目時......這樣可以節省大量的時間,試圖調試/解決您不確定根本原因的問題。

這是一篇美麗的文章,解釋不同類型的保留週期並避免它們。

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

+0

感謝您的鏈接。這是有見地的。 – prabodhprakash