2010-02-08 24 views

Trả lời

131

-initWithNibName:bundle: là trình khởi tạo được chỉ định cho UIViewController. Một cái gì đó cuối cùng nên gọi nó. Điều đó nói rằng, và mặc dù các ví dụ của Apple (có lợi cho ngắn gọn hơn bảo trì trong nhiều trường hợp), nó không bao giờ nên được gọi từ bên ngoài bộ điều khiển xem chính nó.

Bạn sẽ thường xuyên xem mã như thế này:

MYViewController *vc = [[MYViewController alloc] initWithNibName:@"Myview" bundle:nil]; 

Tôi nói điều này là không chính xác. Nó đặt chi tiết thực hiện (tên của NIB và thực tế là một NIB thậm chí được sử dụng) vào người gọi. Điều đó phá vỡ đóng gói. Các cách chính xác để làm điều này là:

MYViewController *vc = [[MYViewController alloc] init]; 

Sau đó, trong MyViewController:

- (instancetype)init 
{ 
    self = [super initWithNibName:@"Myview" bundle:nil]; 
    if (self != nil) 
    { 
     // Further initialization if needed 
    } 
    return self; 
} 

- (instancetype)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle 
{ 
    NSAssert(NO, @"Initialize with -init"); 
    return nil; 
} 

này di chuyển chi tiết thực hiện chốt lại vào đối tượng, và ngăn chặn những người gọi từ vô tình phá vỡ đóng gói. Bây giờ nếu bạn thay đổi tên của NIB, hoặc di chuyển để xây dựng có lập trình, bạn sửa chữa nó ở một nơi (trong bộ điều khiển xem) thay vì ở mọi nơi bộ điều khiển xem được sử dụng.

+3

Nếu đây là con đường dự kiến, tại sao không tạo ra một XCode4 initWithNibName: bó: stub cho mỗi lớp ViewController rỗng, nhưng không có phương pháp init? –

+1

Lý do tương tự là các mẫu không bao gồm tiền tố lớp, mặc dù bạn chắc chắn phải tiền tố cho các lớp của bạn và mẫu tạo ra tên có thể ngu ngốc nhất cho ứng dụng của bạn, đây là một cơn đau đầu thực sự cần khắc phục. Và IB bắt buộc khai báo ivar khi bạn tự động tạo thuộc tính, mặc dù bạn không nên khai báo ivars trong ABI mới. Các mẫu không phải lúc nào cũng là phương pháp hay nhất. Chúng thường là mẫu số ít phổ biến nhất hoạt động phần lớn trong hầu hết các trường hợp, nhưng không có nơi nào đặc biệt tốt. Mã ví dụ của Apple đang được cải thiện gần đây, nhưng nó vẫn có một cách để đi. –

+1

Nếu bạn theo quy ước đặt tên cho ngòi giống như lớp thì mã này hoạt động tốt: '- (id) init { trả về [super initWithNibName: NSStringFromClass ([self class]) bundle: nil]; } ' – CharlesA

6

Sử dụng initWithNibName nếu bạn đang ... khởi tạo bằng tệp nib! Tức là, một tệp mà bạn đã tạo bằng Trình tạo giao diện.

Nếu bạn không sử dụng IB để bố cục chế độ xem của mình, bạn chỉ có thể sử dụng init.

0

sử dụng init khi không có tệp nib/xib, ví dụ: UI được tạo ra bằng cách mã hóa

sử dụng initWithNibName, nếu chúng ta có một nib/xib hoặc cùng phần điều khiển bởi hơn 1 nib/xib

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil]; 
} else { 
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil]; 
} 

đó là những gì tôi nghĩ ..

+0

Bạn biết nếu bạn thêm ~ iphone hoặc ~ ipad vào tên nib của bạn, bạn chỉ có thể gọi initWithNibName @ "ViewController" và nó sẽ chọn đúng. – Darxval

2

Bạn có thể chỉ gọi init, miễn là xib có cùng tên với lớp trình điều khiển xem. Việc đóng gói là không cần thiết. Điều này giúp bạn nhập văn bản nhưng có thể không phục vụ rõ ràng.

NUDMainViewController *mainVC = [[NUDMainViewController alloc] init]; 
Các vấn đề liên quan