2012-05-06 27 views
10

Tôi đến từ một nền Java và tôi đang học Mục tiêu C. Tôi đang cố tạo một lớp có một mảng chuỗi và một hàm thành viên để sửa đổi Mảng. Mã của tôi trông giống như sau:Làm thế nào để khởi tạo một NSMutableArray trong mục tiêu C?

@implementation TAWChapter 

@synthesize mSubject; 

@synthesize mItems; 

- (id) init{ 
    self.mItems = [[NSMutableArray alloc] init]; 
    return self; 
} 

- (void) setSubject:(NSString *)subject{ 
    self.mSubject = subject; 
} 

- (void) addItem:(NSString *)item{ 
    [self.mItems addObject:@"asdf"]; 
} 

@end 

Không hoạt động. Tôi đã nhận được "[__NSArrayI addObject:]: unrecognized selector sent to instance " và một số "NSInvalidArgumentException". Sau khi tìm kiếm trên internet, tôi đã thay đổi dòng đơn trong hàm tạo thành:

self.mItems = [self.mItems init]; 

Nó hoạt động, nhưng tại sao? Từ quan điểm của nhà phát triển Java, quan điểm đầu tiên có ý nghĩa hơn cái thứ hai. Và tôi có một dòng khác nó giống như dòng đầu tiên nhưng nó hoạt động (không phải trong một hàm tạo). Ai đó có thể giải thích điều này cho tôi được không?

+1

Những câu trả lời có lẽ giải quyết vấn đề này, nhưng chúng tôi không thể chắc chắn cho đến khi chúng ta thấy việc kê khai tài sản của 'mItems'. –

Trả lời

27
  1. Đầu tiên của tất cả, bạn nên tuân thủ các quy ước mã hóa Objective-C. Trong Objective-C, các lớp không có các hàm tạo, chúng có các bộ khởi tạo. Trong Objective-C, initialisers gọi initialiser của lớp cha, vì vậy nó sẽ giống như thế này:

    - init 
    { 
        self = [super init]; 
        if (!self) return nil; 
    
        // set up other stuff here 
    
        return self; 
    } 
    
  2. Thứ hai, trừ khi bạn đang sử dụng ARC, bạn có thể có một rò rỉ bộ nhớ. Dòng đầu tiên của trình khởi tạo gán một đối tượng mà bạn sở hữu cho thuộc tính cũng có khả năng sở hữu. Bạn nên sử dụng một trong hai:

    // property takes care of ownership 
    self.mItems = [NSMutableArray array]; 
    

    hay:

    // assign to instance variable directly with owned object 
    mItems = [[NSMutableArray alloc] init]; 
    

    của Apple đôi khi ngăn cản việc sử dụng các phương pháp accessor trong initialisers vì nó có thể fiddle với những thứ như KVO, nhưng việc sử dụng phù hợp các phương pháp accessor đảm bảo quyền sở hữu đối tượng thích hợp và quản lý bộ nhớ.

  3. Bằng cách thay đổi dòng của bạn trong initialiser của bạn để:

    self.mItems = [self.mItems init]; 
    

    không .Khi phương thức initialiser của bạn được gọi (thường là sau khi nó đã được cấp phát), tất cả các biến cá thể được tự động thiết lập là nil. Vì vậy, những gì bạn đang làm chỉ là:

    self.mItems = [nil init]; 
    

    mà chỉ là:

    self.mItems = nil; 
    

    và, không sử dụng init mà không phân bổ một ví dụ, và không bao giờ sử dụng nhiều init hơn một lần.

  4. Nếu bạn không để cho siêu lớp khởi chạy, thì nó có thể biểu hiện như các vấn đề ở các khu vực khác. Làm một số Tạo & Phân tích và đảm bảo bạn đã sửa bất kỳ vấn đề nào được chỉ ra bởi máy phân tích.

+0

Câu trả lời rất hay :) – MJB

+0

Rất cảm ơn :-) – YannickSteph

2

Bạn nên gọi super và gán kết quả của nó để self trong phương pháp init của bạn:

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     self.mItems = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 
6

Vì mục tiêu-c là một superset của c, đó là về cơ bản c với một số "OO" đường cú pháp. Trước khi bạn có thể tạo (hoặc sử dụng!) Một đối tượng, bạn phải phân bổ không gian cho nó trong heap. bạn làm điều này với [Class alloc]. Bước tiếp theo là khởi tạo không gian đó. phân bổ trả về một con trỏ tới không gian đó trong heap, mà bạn khởi tạo với init;)

Vì vậy, bạn gọi Class *myObjc = [[Class alloc] init];.

Nếu bạn sử dụng thừa kế (mà bạn làm từ khi bạn kế thừa từ NSOBject), bạn phải đảm bảo rằng lớp cha của bạn khởi tạo mọi thứ đúng cách, đó là cuộc gọi đến siêu. Để đảm bảo bạn không nhận được một lỗi thời gian chạy, kiểm tra tự = nil, mà bạn làm ngầm với if (tự)

self.mItems = [self.mItems init]; // doesn't do anything, since you call the getter for mItems with self.mItems and try to init. then you try to set mItmes to itself. 

sử dụng mã này:

@implementation TAWChapter 

@synthesize mSubject, mItems; 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     mItems = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (void) setSubject:(NSString *)subject{ 
    mSubject = subject; 
} 

- (void) addItem:(NSString *)item{ 
    [mItems addObject:item]; 
} 

@end 
0

Cách khác có thể được tạo ra từ NSMutableArray NSArray:

NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray]; 
Các vấn đề liên quan