2009-07-25 20 views
13

Đây là mã tôi đang đề cập đến.Điều gì làm tăng số lượng lưu giữ của đối tượng?

// Person.h 

@interface Person : NSObject { 
    NSString *firstName; 
    NSString *lastName; 
} 
@end 

// Person.m 

@implementation Person 
- (id)init { 
    if (![super init]) return nil; 
    firstName = @"John"; 
    lastName = @"Doe"; 
} 
@end 

// MyClass.m 

@implementation MyClass 
    ..... 
- (NSArray *)getPeople { 
    NSMutableArray *array = [[NSMutableArray alloc] init]; 

    int i; 
    for (i = 0; i < 10; i++) { 
     Person *p = [[Person alloc] init]; 
     [array addObject:p]; 
    } 

    return array; 
} 
    ..... 
@end 

Bây giờ, tôi biết không có quản lý bộ nhớ nào đang diễn ra trong mã mẫu này. Điều gì sẽ được yêu cầu?

Trong vòng lặp getPeople, tôi cấp phát một Person (retainCount 1), sau đó thêm nó vào mảng. Số lần giữ lại hiện là 2, phải không? Nếu nó là hai, tôi có nên [p release] 'ing sau khi thêm nó vào mảng, đưa retainCount trở lại xuống 1?

Tôi có đúng là trách nhiệm của người gọi để giải phóng mảng được trả về bằng phương pháp? (Mà cũng sẽ giải phóng bộ nhớ của các cá nhân, và các biến cá thể của chúng, giả định số đếm của chúng là 1).

Tôi đã đọc tài liệu quản lý bộ nhớ của Apple, nhưng tôi đoán những gì tôi không rõ ràng nhất, là những gì tăng một đối tượng giữ lại tính? Tôi nghĩ rằng tôi nắm bắt ý tưởng về trách nhiệm của ai đó là phát hành. Đây là quy tắc cơ bản, theo Apple:

Bạn sở hữu đối tượng nếu bạn tạo một đối tượng có tên bắt đầu bằng “phân bổ” hoặc “mới” hoặc chứa “bản sao” (ví dụ: phân bổ , newObject hoặc mutableCopy) hoặc nếu bạn gửi tin nhắn giữ lại. Bạn chịu trách nhiệm từ bỏ quyền sở hữu đối tượng bạn sở hữu bằng cách sử dụng bản phát hành hoặc tự động phát hành. Bất kỳ lúc nào bạn nhận được một đối tượng, bạn không được giải phóng nó.

Câu của bobDevil "chỉ lo lắng về số lần giữ lại bạn thêm vào mục một cách rõ ràng" khiến nó nhấp cho tôi. Sau khi đọc chính sách Quyền sở hữu tại Apple, về cơ bản, đối tượng/phương thức tạo đối tượng mới, là đối tượng chịu trách nhiệm giải phóng/nó/sở thích trong đó. Điều này có đúng không?

Bây giờ, giả sử tôi là một phương thức nhận một đối tượng và gán nó cho một biến mẫu. Tôi cần phải giữ lại đối tượng nhận được chính xác, vì tôi vẫn còn quan tâm đến nó?

Nếu bất kỳ điều nào trong số này không chính xác, hãy cho tôi biết.

Trả lời

18

Bạn là chính xác rằng giữ lại đếm là 2 sau khi thêm nó vào một mảng. Tuy nhiên, bạn chỉ nên lo lắng về số lần giữ lại mà bạn thêm vào mục một cách rõ ràng.

Giữ lại đối tượng là hợp đồng cho biết "Tôi không làm với bạn, đừng biến mất". Một quy tắc cơ bản của ngón tay cái (có những ngoại lệ, nhưng chúng thường được ghi lại) là bạn sở hữu đối tượng khi bạn phân bổ một đối tượng hoặc tạo một bản sao. Điều này có nghĩa là bạn được cung cấp đối tượng với số lượng giữ lại là 1 (không được tự động phát hành). Trong hai trường hợp đó, bạn nên giải phóng nó khi bạn hoàn thành. Ngoài ra, nếu bạn đã từng giữ một đối tượng rõ ràng, bạn phải giải phóng nó.

Vì vậy, để cụ thể cho ví dụ của bạn, khi bạn tạo một Person, bạn có một số được giữ lại trên đó. Bạn thêm nó vào một mảng (mà làm bất cứ điều gì với nó, bạn không quan tâm) và sau đó bạn đang thực hiện với người, vì vậy bạn phát hành nó:

Person *p = [[Person alloc] init]; //retain 1, for you 
[array addObject:p]; //array deals with p however it wants 
[p release]; //you're done, so release it 

Ngoài ra, như tôi đã nói ở trên, bạn chỉ sở hữu đối tượng trong quá trình phân bổ hoặc sao chép chung, do đó, để phù hợp với điều đó ở phía bên kia của sự vật, bạn nên trả về mảng tự động phát hành, để người gọi phương thức getPeople không sở hữu nó.

return [array autorelease]; 

Chỉnh sửa: Đúng, nếu bạn tạo, bạn phải phát hành nó. Nếu bạn đầu tư vào nó (thông qua giữ lại), bạn phải phát hành nó.

4

Số lượng giữ lại được tăng lên khi bạn gọi phân bổ cụ thể, vì vậy bạn sẽ cần phải giải phóng rõ ràng.

phương pháp nhà máy thường cung cấp cho bạn đối tượng được tự động phát hành (chẳng hạn như [mảng NSMutableArray] - bạn sẽ phải duy trì cụ thể điều này để giữ nó trong khoảng thời gian bất kỳ.).

Theo như NSArray và NSMutableArray addObject :, người khác sẽ phải nhận xét. Tôi tin rằng bạn đối xử với một lớp như hộp đen về cách họ xử lý việc quản lý bộ nhớ của riêng mình như là một mẫu thiết kế, vì vậy bạn sẽ không bao giờ giải phóng một cách rõ ràng thứ gì đó mà bạn đã chuyển vào NSArray. Khi nó bị phá hủy, nó được cho là sẽ xử lý việc giảm số lượng giữ lại.

Bạn cũng có thể giữ lại phần nào tiềm ẩn nếu bạn khai báo ivars của bạn là thuộc tính như @property (giữ lại) suchAndSuchIvar và sử dụng @synthesize trong quá trình triển khai của bạn. Tổng hợp về cơ bản tạo ra setters và getters cho bạn, và nếu bạn gọi ra (giữ lại) cụ thể, setter sẽ giữ lại đối tượng được truyền vào nó.Nó không phải lúc nào ngay lập tức rõ ràng, bởi vì setters có thể được cấu trúc như thế này:

Person fart = [[Person alloc] init]; 
fart.firstName = @"Josh"; // this is actually a setter, not accessing the ivar 
          // equivalent to [fart setFirstName: @"Josh"], such that 
          // retainCount++ 

Edit:

Và như xa như công tác quản lý bộ nhớ, ngay sau khi bạn thêm các đối tượng để mảng, bạn thực hiện với nó ... vậy:

for (i = 0; i < 10; i++) { 
     Person *p = [[Person alloc] init]; 
     [array addObject:p]; 
     [p release]; 
    } 

Josh

2

Bạn nên thường/không/có lo lắng về sự giữ lại đếm. Đó là thực hiện nội bộ. Bạn chỉ nên quan tâm đến việc bạn muốn "sở hữu" một đối tượng bằng cách giữ lại nó. Trong đoạn mã trên, mảng phải sở hữu đối tượng, không phải bạn (bên ngoài vòng lặp mà bạn thậm chí không có tham chiếu đến nó ngoại trừ thông qua mảng). Vì bạn sở hữu [[Person alloc] init], bạn phải giải phóng nó.

Như vậy

Person *p = [[Person alloc] init]; 
[array addObject:p]; 
[p release]; 

Ngoài ra, người gọi của "getPeople" nên không sở hữu mảng. Đây là quy ước. Bạn nên autorelease nó đầu tiên.

NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; 

Bạn sẽ muốn đọc tài liệu hướng dẫn của Apple về quản lý bộ nhớ: http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

+0

Josh nói rằng NSMutableArray được đánh dấu để tự động phát hiện theo mặc định? –

+2

Bạn phải tự động rõ ràng một đối tượng mà bạn tạo. – mjhoy

Các vấn đề liên quan