UIView và initWithFrame và một tệp NIB. Làm cách nào để tải tệp NIB?


75

Tôi có một cuộc UIViewgọi baseViewvà trong đó tôi có initWithFramenơi tôi thêm một số chế độ xem khác và thực hiện một số công cụ tùy chỉnh. Chế độ xem tương tự cũng có tệp NIB.

Bây giờ tôi có một UIViewControllerlớp được đặt tên AppControllertrong đó tôi muốn thêm baseViewchế độ xem vào chế AppControllerđộ xem nên tôi đang thực hiện việc này:

self.view = baseView;nhưng vấn đề là tệp NIB không được tải. Làm cách nào để đảm bảo nội dung tùy chỉnh VÀ tệp NIB được tải / chạy?

Câu trả lời:


167

Bạn có nhiều tùy chọn, tùy thuộc vào cách lớp "baseView" được sử dụng và tích hợp vào ứng dụng của bạn. Không rõ bạn dự định sử dụng lớp này như thế nào - như chế độ xem trong lớp con UIViewController hoặc như một thành phần mô-đun có thể tái sử dụng có nghĩa là được khởi tạo nhiều lần trong suốt ứng dụng của bạn, để sử dụng trong nhiều bộ điều khiển chế độ xem khác nhau.

Nếu chế độ xem của bạn được coi là chế độ xem duy nhất trong lớp con UIViewController, thì Phonitive là chính xác - hãy gói nó cùng với tệp .xib của lớp con UIViewController và sử dụng viewDidLoad của UIViewController để thực hiện lần khởi tạo cuối cùng.

Nhưng nếu bạn muốn lớp View của mình là một thành phần con được sử dụng lại nhiều lần trong các bộ điều khiển chế độ xem khác nhau, được tích hợp thông qua mã hoặc thông qua việc đưa vào tệp .xib cho bộ điều khiển khác, thì bạn cần triển khai cả phương thức initWithFrame: init vàakenFromNib, để xử lý cả hai trường hợp. Nếu quá trình khởi tạo nội bộ của bạn luôn bao gồm một số đối tượng từ .xib, thì trong initWithFrame, bạn sẽ cần tải .xib theo cách thủ công để hỗ trợ các lớp "khách hàng" muốn tạo tiện ích con của bạn thông qua mã. Và tương tự như vậy, nếu tệp .xib có chứa đối tượng của bạn thì bạn sẽ cần đảm bảo rằng bạn gọi bất kỳ quá trình hoàn thiện mã bắt buộc nào từakenFromNib.

Dưới đây là ví dụ về cách tạo thành phần lớp con UIView với thiết kế giao diện người dùng trong nib.

MyView.h:

@interface MyView : UIView
{
    UIView *view;
    UILabel *l;
}
@property (nonatomic, retain) IBOutlet UIView *view;
@property (nonatomic, retain) IBOutlet UILabel *l;

MyView.m:

#import "MyView.h"
@implementation MyView
@synthesize l, view;

- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // Initialization code.
        //
        [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil];
        [self addSubview:self.view];
    }
    return self;
}

- (void) awakeFromNib
{
    [super awakeFromNib];

    // commenters report the next line causes infinite recursion, so removing it
    // [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil];
    [self addSubview:self.view];
}

- (void) dealloc
{
     [l release];
     [view release];
     [super dealloc];
}

Đây là giao diện của tệp nib (ngoại trừ chủ sở hữu của tệp đó cần được thay đổi thành lớp MyView).

nhập mô tả hình ảnh ở đây

hãy chắc chắn kết nối cả cửa hàng chế độ xem và nhãn với Chủ sở hữu tệp. Đó là nó! Mẫu để tạo các tiện ích UIView có thể sử dụng lại.

Điều thực sự gọn gàng về cấu trúc này là bạn có thể đặt các thể hiện của đối tượng MyView của mình trong các tệp nib khác, chỉ cần đặt một UIView ở vị trí / kích thước bạn muốn, sau đó thay đổi lớp trong trình kiểm tra danh tính (CMD-4) thành MyView, và bùng nổ, bạn đã có một phiên bản tiện ích con của mình ở bất kỳ chế độ xem nào bạn muốn! Cũng giống như các đối tượng UIKit, bạn có thể triển khai các giao thức ủy quyền để các đối tượng sử dụng tiện ích con của bạn có thể được thông báo về các sự kiện thú vị và có thể cung cấp dữ liệu để hiển thị trong tiện ích con để tùy chỉnh nó.


1
Thông thường, khi tôi tạo một ứng dụng, tôi muốn tạo một số chế độ xem và tôi muốn sử dụng các chế độ xem đó trong Bộ điều khiển chế độ xem. Tôi không muốn tạo bộ điều khiển chế độ xem cho mỗi chế độ xem, đó là lý do tại sao tôi tạo các chế độ xem riêng biệt mà tôi muốn đưa vào chế độ xem của Bộ điều khiển chế độ xem.
dbrasco

2
Tôi thích thực tế là bạn nói rằng tôi có thể triển khai initWithFrame và wakeFromNib nhưng tôi không chắc mình phải thực hiện kiểu khởi tạo nào và theo thứ tự nào. Bạn có thể đưa ra một ví dụ? Giả sử tôi đã thêm một số nhãn và nút trong XIB với IB. Tôi có một số IBOutlet trong Chế độ xem của mình. Bây giờ tôi muốn trong initWithFrame làm điều gì đó với các đối tượng đó. Làm cách nào để bắt đầu chế độ xem với NIB để nó biết về những đối tượng đó?
dbrasco

2
Thật. Được cấp phép, có một số trường hợp tôi có thể chỉ cần đẩy một chế độ xem VC + khác lên bộ điều khiển điều hướng, nhưng không phải lúc nào cũng vậy. Bây giờ tôi cần phải đọc lại về IBPlugins, f'rinstance: cocoawithlove.com/2009/07/... (chờ đợi, không, không phải iOS cụ thể, nhưng vẫn ...)
Joe D'Andrea

5
loadNibNamed bên awakeFromNib gây đệ quy vô tận
Gargo

1
Đó là sự thật, @Gargo là chính xác, tôi chỉ đang kiểm tra mã này (Câu trả lời tuyệt vời) nhưng tôi đang vào một vòng lặp vô hạn khi khởi tạo, sau khi loại bỏ loadNibNamed bên trong awaleFromNib, sự cố này đã dừng lại. Cảm ơn.
Ospho

3

Tôi tìm thấy bài đăng này sau khi gặp sự cố khi cố gắng thực hiện việc này trong ứng dụng của mình. Tôi đang cố gắng khởi tạo chế độ xem từ NIB trong phương thức ViewDidLoad, nhưng các điều khiển hoạt động như thể chúng đã bị vô hiệu hóa. Tôi đã vật lộn với điều này khi cố gắng đặt trực tiếp thuộc tính userInteractionEnabled và đặt bộ chọn sự kiện cảm ứng theo chương trình cho một nút trong chế độ xem này. Không có gì hoạt động. Tôi tình cờ xem một bài đăng khác và phát hiện ra rằng viewDidLoad có lẽ còn quá sớm để tải NIB này. Tôi đã chuyển tải sang phương thức ViewWillAppear và mọi thứ đều hoạt động. Hy vọng điều này sẽ giúp ai đó đang gặp khó khăn với điều này. Phản hồi chính là tuyệt vời và hoạt động tốt đối với tôi bây giờ tôi đã gọi nó từ một nơi thích hợp.


1
Vui lòng chia sẻ liên kết đến bài đăng khác này với chúng tôi.

Anh ấy có lẽ đã đề cập đến stackoverflow.com/a/819265/779419 . Khi khởi tạo chế độ xem tùy chỉnh, hãy đảm bảo thực sự sử dụng initWithFrame với CGRect thích hợp.
schieferstapel

2

nếu bạn muốn sử dụng NIB, tốt hơn hết là UIView của bạn nên được liên kết với UIViewController, trong trường hợp này, bạn có thể sử dụng

UIViewController *vc=[[UIViewController alloc] initWithNibName:@"YourNIBWihtOUTEXTENSION" bundle:nil]

[self.view addSubView:vc.view ];

do bộ nhớ bị rò rỉ, bạn phải giải phóng vc


Không đúng; Nếu bạn cần thay đổi nội dung của UIView bằng Trình tạo giao diện, bạn sẽ cần sử dụng phương pháp của Bogatyr. Lý do tại sao bạn cần sử dụng UIView kết hợp với Nib là Apple không khuyến khích sử dụng UIViewControllers lồng nhau vì các cuộc gọi cha có thể bị hỏng. Đó là nếu hỗ trợ của bạn <iOS 5. stackoverflow.com/questions/1141015/…
Ospho,

Đây không phải là một việc thực hiện tuyệt vời - tôi muốn nghiên cứu vcs chứa
Adam Waite

0

Nếu bạn có UIView tùy chỉnh với tệp xib.

- (id)initWithFrame:(CGRect)frame
{
   self = [super initWithFrame:frame];

   id mainView;
   if (self)
   {
       NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"HomeAllAdsView" owner:self options:nil];
       mainView = [subviewArray objectAtIndex:0];    
   }
   return mainView;
}

- (void) awakeFromNib
{
   [super awakeFromNib];
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.