2013-09-02 31 views
11

Tôi có một lớp học, FooView, đó là một lớp con của UIView, và có xem được nạp từ một ngòi bút, một cái gì đó như:subclass của một lớp con UIView nạp từ một ngòi

+ (instancetype)viewFromNib 
{ 
    NSArray *xib = [[NSBundle mainBundle] loadNibNamed:@"FooView" owner:self options:nil]; 
    return [xib objectAtIndex:0]; 
} 

Các nib chính nó có Tuỳ chỉnh của nó Lớp học được đặt thành FooView trong Trình kiểm tra danh tính.

này được khởi tạo như:

FooView *view = [FooView viewFromNib]; 

này hoạt động như bạn mong muốn. Tuy nhiên, khi FooView được bản thân subclassed như FooSubclassView, và khởi tạo như:

FooSubclassView *view = [FooSubclassView viewFromNib]; 

view vẫn là loại FooView, không FooSubclassView.

Swizzling lớp với object_setClass không sửa chữa thực tế là các đối tượng cơ bản là một thể hiện của FooView, và do đó phương pháp kêu gọi dụ lớp con sẽ là những của lớp cha (FooView), không FooSubclassView.

Làm thế nào tôi có thể sửa lỗi này để các lớp con thuộc loại chính xác, mà không phải tạo một ngòi mới cho mỗi phân lớp, hoặc phải thực hiện lại viewFromNib trong mỗi phân lớp?

Trả lời

7

Khó xử không phải là câu trả lời.

Sự cố trong NIB của bạn; nó được lưu trữ với đối tượng [0] là một thể hiện của FooView, không phải là FooSubclassView. Nếu bạn muốn tải cùng một số NIB với khác nhau xem lớp con dưới dạng đối tượng [0], bạn cần di chuyển đối tượng ra khỏi lưu trữ của NIB.

Có lẽ điều dễ nhất để làm, vì lớp học của bạn đã được tải NIB, là làm cho một thể hiện của FooView hoặc FooSubclassView các tập tin của chủ sở hữu.

Câu hỏi này có giải thích hợp lý về mẫu Chủ sở hữu của tệp. Lưu ý rằng bạn đã có khá nhiều trong đó lớp của bạn là những gì đang tải XIB/NIB anyway.

Và đây là số docs on File's Owner chính thức.

+0

Tôi không chính xác nhận được điều này. Nếu chế độ xem là Chủ sở hữu tệp thì bạn cần một lớp khác sẽ là "canvas" trực quan mà bạn vẽ bằng cách sử dụng IB, phải không? Xin lỗi nếu câu hỏi này không rõ ràng, nhưng tôi đã có một NIB chỉ với một lớp con NSView trong đó. Cảm ơn bạn! –

1

Tôi không chắc chắn bạn đang đưa ra giải pháp tốt nhất, nhưng tôi nghĩ đây là những gì bạn đang tìm kiếm.

+ (instancetype)viewFromNib 
{ 
    NSString *className = NSStringFromClass([self class]); 
    NSArray *xib = [[NSBundle mainBundle] loadNibNamed:className owner:self options:nil]; 
    return [xib objectAtIndex:0]; 
} 

Điều đó là miễn là bạn có thể chắc chắn rằng NIB có cùng tên với lớp học.


Sau khi nhận ra rằng tôi nhầm một trong các yêu cầu, tôi nói tôi sẽ phải đồng ý với @bbum.

- (id)init 
{ 
    // NOTE: If you don't know the size, you can work this out after you load the nib. 
    self = [super initWithFrame:GCRectMake(0, 0, 320, 480)]; 
    if (self) { 
     // Load the nib using the instance as the owner. 
     [[NSBundle mainBundle] loadNibNamed:@"FooView" owner:self options:nil]; 
    } 
    return self; 
} 

+ (instancetype)viewFromNib 
{ 
    return [[self alloc] init]; 
} 
+0

Điều đó sẽ không hoạt động; bạn đang tải NIB với tên 'className', có nghĩa là bạn sẽ cần một NIB cho mỗi lớp. Ít nhất, tôi không nghĩ đó là những gì OP muốn. Nhưng có lẽ nó là ... – bbum

+0

Vâng darn, tôi đã không nhận thấy yêu cầu đó. –

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