2010-04-27 39 views
8

Tôi đã cố gắng để thiết lập một màu nền UIImageView (xem dưới đây) trong awakeFromNibTruy cập Xem trong awakeFromNib?

[imageView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]]; 

Khi nó đã không làm việc, tôi nhận ra rằng nó có lẽ vì quan điểm đã không nạp được nêu ra và tôi nên di chuyển thay đổi màu sắc để xemDidLoad.

Tôi có thể xác minh rằng mình có quyền này không?

gary

EDIT_002:

Tôi vừa bắt đầu một dự án mới để kiểm tra điều này từ một sự khởi đầu sạch. Tôi thiết lập chế độ xem giống như tôi luôn làm. Kết quả là các điều khiển thực sự được đặt thành (null) trong awakeFromNib. Dưới đây là những gì tôi có:

Mã sản phẩm:

@interface iPhone_TEST_AwakeFromNibViewController : UIViewController { 
    UILabel *myLabel; 
    UIImageView *myView; 
} 
@property(nonatomic, retain)IBOutlet UILabel *myLabel; 
@property(nonatomic, retain)IBOutlet UIImageView *myView; 
@end 

.

@synthesize myLabel; 
@synthesize myView; 

-(void)awakeFromNib { 
    NSLog(@"awakeFromNib ..."); 
    NSLog(@"myLabel: %@", [myLabel class]); 
    NSLog(@"myView : %@", [myView class]); 
    //[myLabel setText:@"AWAKE"]; 
    [super awakeFromNib]; 

} 

-(void)viewDidLoad { 
    NSLog(@"viewDidLoad ..."); 
    NSLog(@"myLabel: %@", [myLabel class]); 
    NSLog(@"myView : %@", [myView class]); 
    //[myLabel setText:@"VIEW"]; 
    [super viewDidLoad]; 
} 

OUTPUT:

awakeFromNib ... 
myLabel: (null) 
myView : (null) 
viewDidLoad ... 
myLabel: UILabel 
myLabel: UIImageView 

tôi sẽ được quan tâm để biết nếu điều này nên làm việc, từ các tài liệu có vẻ như nó nên, nhưng với cách tôi thường thiết lập những điều tôi có thể không hoàn toàn hiểu tại sao nó không trong trường hợp này.

Trả lời

27

Một câu trả lời khác :-) Có vẻ như bạn đang nhận được hành vi này vì bộ điều khiển tải lượt xem một cách lười biếng. Chế độ xem không được tải ngay lập tức, nó được tải lần đầu tiên khi có ai đó gọi cho người truy cập view. Do đó tại thời điểm bạn nhận được awakeFromNib quá trình tải NIB được thực hiện, nhưng không dành cho các đối tượng bên trong chế độ xem của bạn. Xem mã này:

@property(retain) IBOutlet UILabel *foo; 
@synthesize foo; 

- (void) awakeFromNib 
{ 
    NSLog(@"#1: %i", !!foo); 
    [super awakeFromNib]; 
    NSLog(@"#2: %i", !!foo); 
} 

- (void) viewDidLoad 
{ 
    NSLog(@"#3: %i", !!foo); 
} 

này ghi:

#1: 0 
#2: 0 
#3: 1 

Nhưng nếu bạn bắt buộc phải tải các quan điểm:

- (void) awakeFromNib 
{ 
    [super awakeFromNib]; 
    [self view]; // forces view load 
    NSLog(@"#1: %i", !!foo); 
} 

Những thay đổi đăng nhập vào này:

#3: 1 
#1: 1 
+0

Cảm ơn bạn Zoul, điều đó rất thú vị. Tôi đoán tôi chỉ tốt hơn bằng cách sử dụng viewDidLoad như buộc xem để tải các cuộc gọi nó đầu tiên anyways.Tôi cũng đã đọc rằng bằng cách sử dụng awakeFromNib có thể không phải là một ý tưởng tốt trên iPhone, nhưng có vẻ là ý kiến ​​hỗn hợp về điều đó. Cảm ơn một lần nữa ... – fuzzygoat

+0

Nếu bạn không có quyền truy cập vào chế độ xem, sau đó thực hiện lệnh gọi performSelector: withObject: delay từ awakeFromNib. Một hack, nhưng hiệu quả. – phatmann

+0

Chỉ cần vấp phải câu hỏi và câu trả lời này lần đầu tiên - nó sẽ cứu tôi một loạt rắc rối nếu tôi tìm thấy nó trước đó! Vấn đề vẫn tồn tại trong năm 2013 và tôi tin rằng hành vi mâu thuẫn với tài liệu - xem tại đây: http://stackoverflow.com/questions/17400547/awakefromnib-outlets-and-storyboards-is-the-documentation-wrong –

-1

Bạn có chắc chắn rằng các đối tượng không phải là nil? NSAssert hoặc NSParameterAssert là bạn bè:

-(void) awakeFromNib { 
    NSParameterAssert(imageView); 
    NSParameterAssert(testLabel); 
    NSLog(@"awakeFromNib ..."); 
    [imageView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]]; 
    [testLabel setText:@"Pants ..."]; 
    [super awakeFromNib]; 
} 

Nếu các đối tượng đang thực sự khởi tạo, cố gắng đăng nhập địa chỉ của họ và đảm bảo rằng các trường hợp xuất hiện trong viewDidLoad cũng giống như những người trong awakeFromNib:

- (void) awakeFromNib { 
    NSLog(@"test label #1: %@", testLabel); 
} 

- (void) viewDidLoad { 
    NSLog(@"test label #2: %@", testLabel); 
} 

Nếu các số giống nhau, bạn có thể tạo danh mục để đặt điểm ngắt trên setBackgroundColor và xem trong dấu vết ngăn xếp để xem điều gì đang xảy ra:

@implementation UIImageView (Patch) 
- (void) setBackgroundColor: (UIColor*) whatever { 
    NSLog(@"Set a breakpoint here."); 
} 
@end 

Bạn có thể làm các trick tương tự sử dụng một lớp con tùy chỉnh:

@interface PeekingView : UIImageView {} 
@end 

@implementation PeekingView 
- (void) setBackgroundColor: (UIColor*) whatever { 
    NSLog(@"Set a breakpoint here."); 
    [super setBackgroundColor:whatever]; 
} 
@end 

Bây giờ bạn sẽ thiết lập UIViewObject của bạn được của lớp PeekingView trong Interface Builder và bạn sẽ biết khi nào ai cố gắng thiết lập nền. Điều này sẽ bắt trường hợp ai đó ghi đè lên nền thay đổi sau khi bạn khởi tạo chế độ xem trong awakeFromNib.

Nhưng tôi cho rằng vấn đề sẽ đơn giản hơn nhiều, tức là. imageView có lẽ là nil.

+0

Hi Zoul, nhiều đánh giá cao, tôi sẽ đi qua đề xuất của bạn điều đầu tiên vào buổi sáng và để bạn biết làm thế nào tôi nhận được trên. Có lẽ bạn đúng về nó là một cái gì đó đơn giản, hãy để tôi có một cái nhìn tốt hơn. – fuzzygoat

+0

Hi Zoul, các điều khiển thực sự là không, (Xem Edit_002 ở trên) – fuzzygoat

1

Tôi tin rằng cuộc gọi của bạn với siêu cần phải là dòng đầu tiên trong phương thức awakeFromNib, nếu không các yếu tố sẽ không được thiết lập.

-(void)awakeFromNib { 
    [super awakeFromNib]; 
    [imageView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]]; 
    [testLabel setText:@"Pants ..."]; 
} 
+2

Đây là một đoán tốt và 'super' nên được gọi là đầu tiên, nhưng nó không giúp đỡ trong trường hợp này. – zoul

0

Tôi biết, bài đăng này cũ hơn một chút, nhưng gần đây tôi đã có một vấn đề tương tự và muốn chia sẻ giải pháp của nó với bạn.

Có NSTextView được phân lớp, tôi muốn hiển thị màu của hàng theo thứ tự xen kẽ. Để có thể làm thay đổi màu sắc từ bên ngoài, tôi bổ sung thêm hai dụ vars để lớp con của tôi, XNSStripedTableView:

@interface XNSStripedTableView : NSTableView { 

    NSColor *pColor; // primary color 
    NSColor *sColor; // secondary color 
} 

@property (nonatomic, assign) NSColor *pColor; 
@property (nonatomic, assign) NSColor *sColor; 

@end 

ghi đè highlightSelectionInClipRect: không lừa để thiết lập màu sắc chính xác cho các clipRect tương ứng.

- (void)highlightSelectionInClipRect:(NSRect)clipRect 

{

float rowHeight = [self rowHeight] + [self intercellSpacing].height; 
NSRect visibleRect = [self visibleRect]; 
NSRect highlightRect; 

highlightRect.origin = NSMakePoint(NSMinX(visibleRect), (int)(NSMinY(clipRect)/rowHeight)*rowHeight); 
highlightRect.size = NSMakeSize(NSWidth(visibleRect), rowHeight - [self intercellSpacing].height); 

while (NSMinY(highlightRect) < NSMaxY(clipRect)) { 

    NSRect clippedHighlightRect = NSIntersectionRect(highlightRect, clipRect); 
    int row = (int) ((NSMinY(highlightRect)+rowHeight/2.0)/rowHeight); 
    NSColor *rowColor = (0 == row % 2) ? sColor : pColor; 
    [rowColor set]; 
    NSRectFill(clippedHighlightRect); 
    highlightRect.origin.y += rowHeight; 
} 

[super highlightSelectionInClipRect: clipRect]; 

}

Vấn đề duy nhất bây giờ là, nơi để đặt các giá trị ban đầu cho pColor và sColor? Tôi đã cố gắng awakeFromNib :, nhưng điều này sẽ gây ra trình gỡ lỗi để đến với một lỗi. Vì vậy, tôi đào sâu vào vấn đề với NSLog: và tìm thấy một giải pháp dễ dàng nhưng khả thi: thiết lập các giá trị ban đầu trong viewWillDraw:. Vì các đối tượng không được tạo nên gọi phương thức lần đầu tiên, tôi phải kiểm tra nil.

- (void)viewWillDraw { 

if (pColor == nil) 
    pColor = [[NSColor colorWithSRGBRed:0.33 green:0.33 blue:0 alpha:1] retain]; 

if (sColor == nil) 
    sColor = [[NSColor colorWithSRGBRed:0.66 green:0.66 blue:0 alpha:1] retain]; 

}

Tôi nghĩ rằng giải pháp này là :-) khá đẹp mặc dù người ta có thể chọn lại tên của pColor và sColor có thể được điều chỉnh để có nhiều "con người có thể đọc được".

-1

Trong trường hợp bạn đang sử dụng một phân lớp UIView thay vì một lớp con UIViewController, bạn có thể ghi đè lên loadView phương pháp:

- (void)loadView 
{ 
    [super loadView]; 
    //IBOutlets are not nil here. 
} 
Các vấn đề liên quan