2012-02-20 31 views
9

Tôi có một tùy chỉnh UITableViewCell mà tôi đang instantiating từ một ngòi sử dụng instantiateWithOwner:(id)owner options:(NSDictionary *)options. Khi nib được khởi tạo, tôi đang lưu nó vào một IBOutlet được định nghĩa trong bộ điều khiển xem của tôi, được đặt làm chủ sở hữu của tệp trong tệp .xib. Mọi thứ đều hoạt động tốt.Sử dụng id <protocol> cho chủ sở hữu tệp trong Trình tạo giao diện?

Tôi hiện đang gặp phải sự cần thiết phải sử dụng ô tùy chỉnh này trong nhiều bộ điều khiển chế độ xem. Tôi đã hy vọng rằng tôi có thể xác định một giao thức (ví dụ: CustomCellOwner), mà nhiều bộ điều khiển xem có thể thực hiện. Giao thức sẽ chỉ định IBOutlet được sử dụng để tham chiếu ô khi được khởi tạo.

Vì vậy, lý tưởng, tôi muốn thiết lập "chủ sở hữu tập tin" để:

id <CustomCellOwner> 

trong Interface Builder.

Tuy nhiên, Trình tạo giao diện dường như chỉ cho phép bạn đặt chủ sở hữu tệp thành một lớp đã biết, không phải cho một id triển khai giao thức?

Có cách nào để thực hiện việc này không? Hoặc, một cách đơn giản hơn để tiếp cận vấn đề này?

Cảm ơn!

+0

Hoàn thành sidenote, bạn có thể chỉ cho tôi một số hướng dẫn hoặc mẫu làm thế nào bạn đang làm điều này bởi vì nó âm thanh tuyệt vời, hiện tại tôi phải lặp qua một ngòi để tìm xem thích hợp để sử dụng trong các tế bào tùy chỉnh của tôi. Đây không phải là lý tưởng. Và có vẻ như bạn có một giải pháp tuyệt vời. –

+0

Bạn có thể xây dựng trên "nó chỉ dường như cho phép bạn đặt chủ sở hữu tệp cho một lớp đã biết, không phải là một id triển khai giao thức không?" Nó có nghĩa là người xây dựng giao diện? – rooftop

+0

@rooftop có, "nó" đề cập đến Interface Builder trong trường hợp đó. Khi chỉnh sửa/định cấu hình đối tượng chủ sở hữu của tệp, có tùy chọn "Lớp" cho phép bạn chọn lớp của chủ sở hữu tệp. Hộp đó trong IB không cho phép tôi nhập id làm kiểu, và tôi tự hỏi nếu điều này là có thể. Cảm ơn! – thauburger

Trả lời

3

Đây không phải là giải pháp bạn đang yêu cầu, nhưng bạn có thể tạo lớp con UIViewController mà bạn phân lớp cho từng bộ điều khiển chế độ xem cần sử dụng ngòi bút của bạn. Một cái gì đó như:

@interface CustomCellOwnerViewController : UIViewController 
@property (nonatomic, strong) IBOutlet UIButton *someButton; 
-(IBAction)doSomething; 
@end 

Và sau đó sử dụng như là lớp cơ sở cho mỗi:

@interface FirstView : CustomCellOwnerViewController 

Sau đó, bạn có thể chỉ cần đặt File's Owner-CustomCellOwnerViewController không có vấn đề.

Chỉ là một ý tưởng.

1

Tôi đã gặp phải điều này ngày hôm nay và không tìm thấy giải pháp tốt. Tôi đã làm tuy nhiên hack nó để nó có vẻ làm việc ok. Nó chắc chắn cảm thấy như một hack mặc dù.

Trước tiên tôi tạo ra một lớp "fakeOwner" như thế này:

@interface fakeOwner : NSObject 
@property (nonatomic, assign) IBOutlet MyBaseCell* itemTableCell; 
@end 

@implementation fakeOwner 
@synthesize itemTableCell; 
@end 

sau đó tôi đặt chủ sở hữu của đối tượng trong XIB như fakeOwner và kết nối với ổ cắm. Sau đó, cho mỗi bộ điều khiển mà muốn sử dụng những tế bào này tôi thêm các thuộc tính giống nhau và tạo ra các lớp học như thế này:

[[NSBundle mainBundle] loadNibNamed:@"MyBaseCell" owner:self options:nil]; 
    MyBaseCell* itemCell = self.itemTableCell; 
    self.itemTableCell = nil; 

Kể từ khi fakeOwner và điều khiển của tôi có cùng một IBOutlet, tải các tế bào với bộ điều khiển như những nguyên nhân chủ sở hữu kết nối xảy ra mặc dù đó không phải là những gì được thiết lập rõ ràng trong XIB.

Không 100% nếu quản lý bộ nhớ hiện tại (tôi nghĩ là không sao), nhưng ngoài ra nó có vẻ hoạt động tốt. Tôi rất thích nhìn thấy một cách tốt hơn để làm điều này mặc dù.

+0

Thú vị làm việc xung quanh. Cảm ơn các đầu vào! – thauburger

1

Làm cho chủ sở hữu giả sẽ hoạt động; tuy nhiên, một giải pháp như vậy có thể mong manh và không thể đọc được. Trong một ý nghĩa, các tế bào sở hữu chính nó, nhưng ngay cả đó là về mặt kỹ thuật không chính xác. Sự thật là UITableViewCell s không có chủ sở hữu.

Cách thích hợp để triển khai các ô xem bảng tùy chỉnh là trước tiên tạo một lớp con tùy chỉnh của UITableViewCell.Trong lớp này, bạn sẽ định nghĩa tất cả các IBOutlets và cho các ô đó. Đây là một mẫu của một tập tin tiêu đề:

@interface RBPersonCell : UITableViewCell 

@property (nonatomic, strong) IBOutlet UILabel * nameLabel; 
@property (nonatomic, strong) IBOutlet UILabel * ageLabel; 

- (void)setupWithPerson:(Person *)person; 

@end 

Từ đó, tôi có một phương pháp tiện lợi mà tạo ra các tế bào từ ngòi, nếu cần thiết:

+ (id)cellForTableView:(UITableView *)tableView reuseIdentifier:(NSString *)reuseID fromNib:(UINib *)nib { 

    if (!reuseID) 
     reuseID = [self cellIdentifier]; 

    id cell = [tableView dequeueReusableCellWithIdentifier:reuseID]; 

    if (!cell) { 

     NSArray * nibObjects = [nib instantiateWithOwner:nil options:nil]; 

     // Sanity check. 
     NSAssert2(([nibObjects count] > 0) && 
        [[nibObjects objectAtIndex:0] isKindOfClass:[self class]], 
        @"Nib '%@' does not appear to contain a valid %@", 
        [self nibName], NSStringFromClass([self class])); 

     cell = [nibObjects objectAtIndex:0]; 
    } 

    return cell; 
} 

Phương pháp này gói gọn tất cả các mã tạo vì vậy tôi không bao giờ phải xem hoặc viết lại. Nó giả định rằng ô tùy chỉnh là khung nhìn gốc đầu tiên trong ngòi bút. Đây là một giả định khá an toàn vì bạn chỉ nên có ô tùy chỉnh làm chế độ xem gốc.

Với tất cả mã này tại chỗ, bạn đã sẵn sàng làm việc trong Trình tạo giao diện. Trước tiên, bạn cần đặt lớp tùy chỉnh trong kiểm tra danh tính. Tiếp theo, đừng quên đặt định danh ô của bạn. Để thuận tiện, tốt nhất bạn nên sử dụng tên của lớp tùy chỉnh. Khi bạn kéo các kết nối của mình, thay vì kéo chúng vào Chủ sở hữu tệp, hãy kéo các kết nối của bạn vào chính ô tùy chỉnh.

Hầu hết những gì tôi đã tìm hiểu về các ô xem bảng tùy chỉnh đều xuất phát từ iOS Recipes công thức nấu ăn 15-16. Đây là số free extract trực tiếp từ The Pragmatic Bookshelf. Bạn có thể xem cuốn sách đó để biết thêm chi tiết.

EDIT:

cuối cùng tôi nhận được xung quanh để mở nguồn lớp RBSmartTableViewCell tôi. Bạn có thể tìm thấy nó trên GitHub của tôi. Bạn sẽ thấy lớp này hữu ích hơn mã trực tiếp từ iOS Recipes, vì lớp của tôi xử lý tất cả các ô giống nhau, bất kể chúng được xây dựng bằng XIB, UIStoryboard hay mã. Repo này cũng bao gồm các mẫu làm việc.

1

Trong iOS 5.0 hiện có phương pháp registerNib:forCellReuseIdentifier: trên UITableView mà tôi tin rằng các nỗ lực để giải quyết vấn đề tương tự.

Từ các tài liệu:

Khi bạn đăng ký một đối tượng ngòi với quan điểm bảng và sau đó gọi phương thức dequeueReusableCellWithIdentifier:, đi qua trong định danh đã đăng ký, xem bảng instantiates các tế bào từ các đối tượng nib nếu nó là chưa có trong hàng đợi sử dụng lại.

Đây có thể là phương pháp thay thế tùy theo yêu cầu của bạn.

1

Một tùy chọn khác có thể là tạo đối tượng 'nhà máy' nhẹ để xử lý việc tạo các ô cho bạn. Đối tượng này sẽ là FilesOwner trong trình tạo giao diện, với lối ra rootObject được đặt thích hợp.

@interface NibLoader : NSObject 

@property (nonatomic, strong) UINib  * nib; 
@property (nonatomic, strong) IBOutlet id rootObject; 

- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)bundleOrNil; 
- (id)instantiateRootObject; 

@end 


@implementation NibLoader 

@synthesize nib, rootObject; 

- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)bundleOrNil { 
    self = [super init]; 
    if (self) { 
     self.nib = [UINib nibWithNibName:name bundle:bundleOrNil]; 
    } 
    return self; 
} 

- (id)instantiateRootObject { 
    self.rootObject = nil; 
    [self.nib instantiateWithOwner:self options:nil]; 
    NSAssert(self.rootObject != nil, @"NibLoader: Nib did not set rootObject."); 
    return self.rootObject; 
} 

@end 

Sau đó, trong bộ điều khiển xem:

NibLoader *customCellLoader = [[NibLoader alloc] initWithNibName:@"CustomCell" bundle:nil]; 
self.customCell = customCellLoader.instantiateRootObject; 

Tôi thích thiết lập một cách rõ ràng đối tượng gốc thay vì tìm kiếm thông qua các mảng trở về từ instantiateWithOwner:options: bởi vì tôi biết vị trí của các đối tượng trong mảng này đã thay đổi trong quá khứ.

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