2012-04-27 16 views
5

Dường như trong ví dụ mã của một cuốn sách, init luôn được xác định để cẩn thận kiểm tra xem self có thể tồn tại hay không.Trong Mục tiêu-C, cách xử lý [[myView alloc] init] trở về nil?

-(id) init { 

    self = [super init]; 
    if (self) { 
     // initialize 
    } 
    return self; 
} 

Tuy nhiên, khi trả lại, không có mã nào kiểm tra xem đối tượng có thể tồn tại hay không. Nhưng nó nên được kiểm tra, và làm thế nào nó có thể được xử lý? Nếu đối tượng không thể tồn tại, điều đó có nghĩa là hệ thống đang nghiêm trọng ra khỏi bộ nhớ, và thậm chí popping lên một thông báo lỗi cũng sẽ là không thể?

+0

Đây thực sự là một câu hỏi khá hay. Tôi biết tôi không bao giờ kiểm tra nếu tôi nhận được một cái gì đó từ kết quả của loại chức năng, tôi chỉ giả định rằng phân bổ/init làm việc (trừ khi làm việc với một cái gì đó mất & lỗi, đại diện cho một cái gì đó mà có cơ hội thất bại). Một câu hỏi rất thú vị thực sự. – RonLugge

+0

có thể trùng lặp của [In Objective-C tại sao tôi nên kiểm tra nếu self = \ [super init \] không phải là nil?] (Http://stackoverflow.com/questions/1287950/in-objective-c-why-should- i-check-if-self-super-init-is-not-nil) – omz

Trả lời

4

Tuy nhiên, khi trả lại, không có mã nào trong tất cả kiểm tra xem đối tượng có thể tồn tại hay không. Nhưng nó nên được kiểm tra, và làm thế nào nó có thể được xử lý?

Thông thường, việc xử lý lỗi bị bỏ qua bởi các lớp con khi trả về nil. Xử lý lỗi thường được để lại cho người gọi khi trả lại nil. Như thể hiện trong thành ngữ -init:

- (id)init { 
    self = [super init]; 
    if (self) { 
    // initialize 
    } 
    return self; 
} 

như tốt, nếu căn cứ reallocates self trong init, sau đó self được bố trí (self = [super init];). hoạt động tốt.

Nếu bạn thất bại trong việc gán self đến kết quả của initializer super 's hoặc nếu bạn thất bại trong việc kiểm tra nil, sau đó bạn có thể được tổ chức vào một lơ lửng/con trỏ deallocated (EXC_BAD_ACCESS), và bạn có thể không khởi ivars của bạn đúng cách (bạn sẽ gán chúng hiệu quả cho một khu vực khác nếu không gặp phải EXC_BAD_ACCESS).

Hai trường hợp chi tiết hơn:

Fail gán tự

- (id)init { 
    [super init]; 
    if (self) { 
    // self was not reassigned. if super returned an object other 
    // than self, then our ivar would be freed, reused, or sitting 
    // in an autorelease pool, and the returned instance's ivar 
    // would not be assigned -- we wouldn't know the address. 
    ivar = 1; 
    } 
    return self; 
} 

Fail để kiểm tra nil

- (id)init { 
    self = [super init]; 
    // super returned nil. ivar is an invalid region: 
    ivar = 1; 
    return self; 
} 

và vâng, tôi đã thấy cả hai những cái này


Nếu đối tượng không thể tồn tại, không có nghĩa hệ thống là nghiêm trọng ra khỏi bộ nhớ, và thậm chí nảy lên một thông báo lỗi cũng sẽ không thể?

Không hề. Nhiều trình khởi tạo trả về nil để nói "không thể thực hiện trong ngữ cảnh này" hoặc nếu có lỗi tham số đơn giản.

+0

Xin lỗi, tôi không hiểu làm thế nào bạn sẽ có một con trỏ lơ lửng nếu bạn không kiểm tra nil. Nếu bạn không kiểm tra nil, thì bạn sẽ gửi thư đến nil một cách hiệu quả nếu không có nil và chúng sẽ bị bỏ qua. – borrrden

+0

Ah, tôi thấy rằng nó thực sự là phần thứ 2 (chuyển nhượng lại bản thân) mà bạn đang nói đến. Nevermind ^^; – borrrden

+0

@ borrrden tôi thấy bạn đã thấy bản cập nhật mà tôi đã tạo cho bạn :) có, nhắn tin * có thể * an toàn, nếu bản thân là nil và bạn đã nhắn tin trong bộ khởi tạo của mình. tuy nhiên, khởi tạo và dealloc là các trạng thái được xây dựng một phần đặc biệt. mọi người tranh luận cho cả hai bên, nhưng khởi tạo trực tiếp nói chung là cách an toàn hơn để khởi tạo một đối tượng, thay vì sử dụng các trình truy cập trong init/dealloc. Không kiểm tra nil cũng là một rủi ro, như đã chứng minh. – justin

3

Điều đó có nghĩa là hệ thống nghiêm trọng ra khỏi bộ nhớ

số Một thất bại trong việc cấp phát bộ nhớ nói chung sẽ gây ra + alloc thất bại, không init.

Thực tế, phương pháp init không có đối số nào là không phổ biến. Thông thường, các phương thức init có thể trả về nil nếu bạn đã truyền các đối số không hợp lệ, ví dụ NSString's -initWithContentsOfFile: có thể trả về nil nếu nó không tải được nội dung của đường dẫn tệp mà nó được cho là được khởi tạo.

Đó có lẽ là điều bạn muốn kiểm tra xem bạn có nhận thức được khả năng đáng kể về lỗi init hay không, nếu không, bạn chỉ nên tiếp tục sử dụng đối tượng.

+0

Ngoài ra, trên iOS, nếu hệ thống hết bộ nhớ thì bạn sẽ bị hủy bỏ. –

+0

@KevinBallard, vâng, ứng dụng sẽ bị giết trước khi phân bổ bộ nhớ không thành công. Và trên OS X, có một không gian bộ nhớ ảo khổng lồ trong 64 bit cho thấy rằng một ứng dụng sẽ hết bộ nhớ. – joerick

+0

iOS sẽ sử dụng bộ nhớ Flash còn lại làm bộ nhớ ảo? (chẳng hạn như nếu iPhone 16GB có 3GB miễn phí) ... tuy nhiên, iPhone của tôi có đầy đủ các bài hát do tải xuống tự động mà chỉ 20MB miễn phí ngay bây giờ. –

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