Theo như tôi có thể nói, đôi khi thực sự cần thiết phải phân lớp UINavigationBar, để thực hiện một số cấu trúc lại không theo tiêu chuẩn. Đôi khi bạn có thể tránh phải làm như vậy bằng cách sử dụng các danh mục , nhưng không phải lúc nào cũng vậy.
Hiện tại, theo như tôi biết, cách duy nhất để đặt UINavigationBar tùy chỉnh trong UIViewController là thông qua IB (tức là thông qua một kho lưu trữ) - có lẽ không nên như vậy, nhưng hiện tại, chúng ta phải sống với nó.
Điều này thường ổn, nhưng đôi khi sử dụng IB không thực sự khả thi.
Vì vậy, tôi đã thấy ba tùy chọn:
- Subclass UINavigationBar và kết nối tất cả trong IB, sau đó bắt đầu tải lên nib mỗi khi tôi muốn có UINavigationController,
- Sử dụng phương thức thay thế trong một danh mục để thay đổi hành vi của UINavigationBar, thay vì phân lớp, hoặc
- Subclass UINavigationBar và thực hiện một chút thao tác với việc lưu trữ / hủy lưu trữ UINavigationController.
Tùy chọn 1 là không khả thi (hoặc ít nhất là quá khó chịu) đối với tôi trong trường hợp này, vì tôi cần tạo UINavigationController theo lập trình, 2 hơi nguy hiểm và theo ý kiến của tôi là tùy chọn cuối cùng, vì vậy tôi đã chọn tùy chọn 3.
Cách tiếp cận của tôi là tạo một kho lưu trữ 'mẫu' của một UINavigationController và hủy lưu trữ nó, trả lại nó initWithRootViewController
.
Đây là cách thực hiện:
Trong IB, tôi đã tạo một UINavigationController với lớp thích hợp được đặt cho UINavigationBar.
Sau đó, tôi lấy bộ điều khiển hiện có và lưu bản sao lưu trữ của nó bằng cách sử dụng +[NSKeyedArchiver archiveRootObject:toFile:]
. Tôi vừa thực hiện việc này trong ứng dụng ủy quyền, trong trình mô phỏng.
Sau đó, tôi đã sử dụng tiện ích 'xxd' với cờ -i, để tạo mã c từ tệp đã lưu, để nhúng phiên bản đã lưu trữ vào lớp con ( xxd -i path/to/file
) của tôi .
Trong initWithRootViewController
Tôi hủy lưu trữ mẫu đó và tự đặt thành kết quả của quá trình hủy lưu trữ:
// This is the data from [NSKeyedArchiver archivedDataWithRootObject:controller], where
// controller is a CTNavigationController with navigation bar class set to CTNavigationBar,
// from IB. This c code was created using 'xxd -i'
static unsigned char archived_controller[] = {
0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd4, 0x01, 0x02, 0x03,
...
};
static unsigned int archived_controller_len = 682;
...
- (id)initWithRootViewController:(UIViewController *)rootViewController {
// Replace with unarchived view controller, necessary for the custom navigation bar
[self release];
self = (CTNavigationController*)[NSKeyedUnarchiver unarchiveObjectWithData:[NSData dataWithBytes:archived_controller length:archived_controller_len]];
[self setViewControllers:[NSArray arrayWithObject:rootViewController]];
return [self retain];
}
Sau đó, tôi chỉ có thể lấy một phiên bản mới của lớp con UIViewController của tôi có bộ thanh điều hướng tùy chỉnh:
UIViewController *modalViewController = [[[CTNavigationController alloc] initWithRootViewController:myTableViewController] autorelease];
[self.navigationController presentModalViewController:modalViewController animated:YES];
Điều này mang lại cho tôi một UITableViewController phương thức với thanh điều hướng và thanh công cụ đều được thiết lập và với lớp thanh điều hướng tùy chỉnh tại chỗ. Tôi không cần phải thực hiện bất kỳ thay thế phương pháp hơi khó chịu nào và tôi không phải bận tâm về ngòi khi tôi thực sự chỉ muốn làm việc theo chương trình.
Tôi muốn thấy tương đương với +layerClass
bên trong UINavigationController - +navigationBarClass
- nhưng hiện tại, điều này hoạt động.