2008-12-31 19 views
5

Tôi có lớp sau Ví dụ:Mục tiêu sở hữu C NSString * giữ lại đếm kỳ quặc

Test.h:

@interface Test : UIButton { 
    NSString *value; 
} 
- (id)initWithValue:(NSString *)newValue; 
@property(copy) NSString *value; 

Test.m:

@implementation Test 
@synthesize value; 
- (id)initWithValue:(NSString *)newValue { 
    [super init]; 
    NSLog(@"before nil value has retain count of %d", [value retainCount]); 
    value = nil; 
    NSLog(@"on nil value has retain count of %d", [value retainCount]); 
    value = newValue; 
    NSLog(@"after init value has retain count of %d", [value retainCount]); 
    return self; 
} 

nào xuất ra như sau:

2008-12-31 09:31:41.755 Concentration[18604:20b] before nil value has retain count of 0 
2008-12-31 09:31:41.756 Concentration[18604:20b] on nil value has retain count of 0 
2008-12-31 09:31:41.757 Concentration[18604:20b] after init value has retain count of 2147483647 

Tôi gọi ing it like:

Test *test = [[Test alloc] initWithValue:@"some text"]; 

Giá trị không được tính là 1? Tôi đang thiếu gì?

Cảm ơn sự giúp đỡ của bạn.

Trả lời

3

Bạn có tham chiếu đến một chuỗi không thể thay đổi. Nhiệm vụ không cần phải sao chép giá trị (dữ liệu chuỗi) vì nó không thay đổi được. Nếu bạn thực hiện thao tác có thể thay đổi, như giá trị = [newValue uppercaseString] thì nó sẽ sao chép các bit thành giá trị và số lượng giữ lại của giá trị tăng lên.

+1

Điều này không thực sự giải quyết các vấn đề cơ bản với mã của poster ban đầu: Anh ta không tuân theo các quy tắc quản lý bộ nhớ, và anh ta gán trực tiếp cho một biến cá thể thay vì đi qua thuộc tính. –

10

Bạn đang chuyển một chuỗi chữ. Trình biên dịch có thể phân bổ nó trong bộ nhớ tĩnh và đặt số lượng giữ lại thành giá trị tối đa có thể.

Hãy thử một chuỗi được phân bổ động thay vào đó và xem điều gì sẽ xảy ra.

NSString* string = [[NSString alloc] initWithString: @"some text"]; 
Test* test = [[Test alloc] initWithValue: string]; 
+0

nó phân bổ nó trong bộ nhớ tĩnh mặc dù tôi sử dụng thuộc tính sao chép trên thuộc tính? –

+0

Nếu bạn muốn sử dụng thuộc tính, bạn phải nói "self.value = anything" thay vì chỉ "value = whatever", mà chỉ đơn giản gán biến dụ. –

+2

hoàn thành .. cùng một lỗi. Tôi cũng đã thử sử dụng mã chuỗi động ở trên. –

3

Bạn đang chuyển một chuỗi không đổi, điều này thực sự không thể được phân bổ. Tôi nghĩ rằng 2147483647 có lẽ là UINT_MAX, về cơ bản có nghĩa là đối tượng không thể được phát hành.

+0

không thuộc tính sao chép tạo một bản sao mới không có trong bộ nhớ tĩnh? –

+0

Điểm sẽ là gì? Bạn không thể thay đổi giá trị, vì vậy bạn cũng có thể trỏ vào bộ nhớ tĩnh. Có thể đáng thử thay đổi kiểu thành NSMutableString để xem bạn có nhận được cùng một hành vi hay không. –

+0

nó có thể cho một bản sao để thực sự -retain bản gốc khi bản gốc là bất biến, do đó, một bản sao sẽ được đảm bảo giống hệt nhau. –

3

Tôi nghĩ rằng bạn muốn làm điều này:

self.value = newValue; 

mà sẽ gọi setter tài sản và gây ra các bản sao để xảy ra. "value = newValue" chỉ đơn giản gán giá trị con trỏ cho biến mẫu.

+0

cảm ơn, .. tôi đã thực hiện thay đổi ..vẫn còn lỗi tương tự –

0

hmm .. chúng tôi đang tiến gần hơn.

dường như giữ lại đếm newValue cũng 2147483647.

Tôi đã cố gắng tự động phân bổ các chuỗi là thay vì với cùng một kết quả duy trì đếm.

Tôi tìm thấy một bài viết hữu ích ở đây: http://www.cocoadev.com/index.pl?NSString

FTA:

Liệu NSString trả về bởi @ "" cần phải được phát hành, hoặc là nó autoreleased? Không. @ "" - chuỗi là lớp NSConstantString ?, và do đó hoạt động như các nguyên tử trong lisp; họ treo xung quanh. Tức là, nếu bạn sử dụng @ "bò" ở hai vị trí riêng biệt trong mã của bạn, chúng sẽ tham chiếu đến cùng một đối tượng. Tôi không nghĩ rằng -release hoặc -autorelease làm bất cứ điều gì cho một trong số họ.

Nếu tôi có "sao chép" trên thuộc tính, không nên sao chép nội dung của bộ nhớ đích vào bộ nhớ mới với số lượng giữ lại là 1? Có vẻ như thuộc tính copy không làm gì trong trường hợp này?

+0

Đây là sự hiểu biết của tôi: Khi bạn làm một "bản sao" trên một đối tượng bất biến, bạn thực sự chỉ giữ lại nó. Làm một bản sao của một chuỗi có thể thay đổi (hoặc đối tượng có thể thay đổi khác) thực sự sao chép nó. Đừng quá hung hăng về toàn bộ điều lưu giữ. Nếu bạn cân bằng mọi phân bổ với bản phát hành, bạn sẽ làm tốt. –

21

Đừng xem xét số lượng giữ lại. Chúng không hữu ích và sẽ chỉ đánh lừa bạn - bạn không thể chắc chắn rằng không có gì khác đang giữ lại một đối tượng, rằng một đối tượng bạn nhận được từ đâu đó không được chia sẻ.

Thay vào đó, hãy tập trung vào quyền sở hữu đối tượng và theo dõi Cocoa memory management rules vào thư. Bằng cách đó, quản lý bộ nhớ của bạn sẽ chính xác cho dù tối ưu hóa Cocoa có thể làm gì sau hậu trường cho bạn. (Ví dụ, thực hiện -copy như chỉ -retain cho các đối tượng không thay đổi.)

Hơn nữa, nó là quan trọng hiểu sự khác biệt giữa tính đối tượng của bạn và biến dụ trong đối tượng của bạn. Trong mã câu hỏi của bạn, bạn đang gán một giá trị cho một biến cá thể. Biến cá thể đó chỉ là: một biến. Việc gán cho nó sẽ hoạt động giống như bất kỳ phép gán biến nào khác. Để sử dụng tài sản, bạn phải sử dụng một trong hai dot cú pháp hoặc cú pháp khung để thực sự gọi phương thức setter của khách sạn:

self.value = newValue;  // this is exactly equivalent to the next line 
[self setValue:newValue]; // this is exactly equivalent to the previous line 

Mã này tạo ra cho dấu chấm cú pháp và cú pháp khung là giống hệt nhau, và không phải sẽ truy cập vào instance variable trực tiếp.

0
#import <Foundation/Foundation.h> 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    char *cstr = "this is a c string"; 

    NSString *str = [[NSString alloc] initWithUTF8String:cstr]; 
    NSLog(@"rc1: %d", [str retainCount]); 

    [pool drain]; 
    return 0; 
} 

Nếu bạn chạy đoạn mã trên, nó sẽ hiển thị một số giữ lại trong tổng số 1

0

Trong Cocoa, nhiều đối tượng bất biến sẽ chỉ đơn giản là giữ lại chính mình khi bạn yêu cầu một bản sao trong vùng tương tự. Nếu đối tượng được đảm bảo không thay đổi (nghĩa là tính bất biến của nó) thì một bản sao chính xác là không cần thiết.

Trong Mục tiêu-C, lớp chuỗi liên tục tách biệt với lớp NSString của Cocoa, mặc dù nó có thể là một phân lớp của NSString (Tôi không quá chắc chắn). Lớp chuỗi không đổi này có thể ghi đè các phương thức của NSObject như retain, releasedealloc để chúng không thực hiện gì và cũng ghi đè retainCount để luôn trả về cùng một số, UINT_MAX hoặc hơn. Điều này là do một chuỗi liên tục Objective-C được tạo ra trong bộ nhớ tĩnh. Nó phải có hành vi chung chung của một đối tượng Cocoa (khi sử dụng Cocoa) để nó có thể được thêm vào mảng, được sử dụng làm khóa cho từ điển, ngoại trừ việc quản lý bộ nhớ của nó, vì nó được phân bổ khác nhau.

Tuyên bố từ chối trách nhiệm: Tôi thực sự không biết mình đang nói về điều gì.

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