2009-05-16 40 views
12

Điều gì là đúng? Đây:Quản lý bộ nhớ và thực hiệnSelectorInBackground:

NSArray* foo = [[NSArray alloc] initWithObjects:@"a", @"b", nil]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    ... 
    [foo release]; 
} 

Hoặc:

NSArray* foo = [[[NSArray alloc] initWithObjects:@"a", @"b", nil] autorelease]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    ... 
    [pool release]; 
} 

Tôi biết người đầu tiên hoạt động, nhưng Clang phàn nàn về điều đó, vì vậy tôi tự hỏi, nếu có một mô hình tốt hơn để sử dụng.

tôi sẽ "chỉ thử" người thứ 2, nhưng với autoreleasing, ai mà biết được liệu sự vắng mặt của EXC_BAD_ACCESS có nghĩa là bạn đang làm đúng hay mà bạn chỉ có may mắn ...

Trả lời

24

Đầu tiên là sai .

performSelectorInBackground: withObject: giữ lại cả hai thanh và foo cho đến khi tác vụ được thực hiện. Do đó, bạn nên tự động chạy foo khi tạo và để performSelectorInBackground: withObject quản lý phần còn lại. Xem documentation

Vấn đề là chính xác vì bạn tự động phát foo khi tạo. Autorelease pool mà bạn tạo bên trong baz không có gì liên quan đến tính đúng đắn của quản lý bộ nhớ của foo. Đó là hồ bơi autorelease là cần thiết cho các đối tượng autoreleased bên trong phân bổ hồ bơi và phát hành trong baz, nó không chạm vào số lượng giữ lại của foo cả.

+1

Ồ, nó phải có trong tài liệu! Tôi ngớ ngẩn quá. :) – lawrence

+4

Tôi nên làm rõ: bạn PHẢI tạo và thoát một nhóm autorelease bên trong -baz :, trừ khi bạn BIẾT rằng không có gì sẽ được gửi một phương pháp -autorelease bên trong đó. Nguyên tắc tốt nhất là giả định rằng điều đó sẽ xảy ra và tạo/thoát một nhóm tự động phát hành, như trong ví dụ 2. Nhưng sử dụng [pool drain], không phải [release pool]. –

+0

Chính xác như Jim Dovey đã nói: bạn thường cần tạo hồ bơi autorelease giống như bạn làm cho chức năng chính (xem Hướng dẫn lập trình chủ đề). Nó chỉ là quan trọng để hiểu rằng hồ bơi này không có gì để làm với autorelease của foo. –

2

Cách tiếp cận đúng bây giờ sẽ trong thực tế có thể làm:

NSArray* foo = [[[NSArray alloc] initWithObjects:@"a", @"b", nil] autorelease]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    @autoreleasepool { 
     ... 
    } 
}