2010-04-27 40 views
8

我一直在尝试awakeFromNib访问awakeFromNib中的视图?

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

设置一个UIImageView的背景颜色(见下文),当没有工作,我意识到,它可能是因为视图尚未加载,我应该搬到颜色变化viewDidLoad。

我可以证实我有这个权利吗?

加里

EDIT_002:

我刚开始一个新的项目,从一个干净的开始检查。我设置的视图与我一直所做的一样。结果是在awakeFromNib中的控件确实设置为(null)。以下是我有:

CODE:

@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 

我很想知道,如果这应该工作,从它的外观的文档像它应该,但由于我平时做一些事情,我不能完全不一样的理解为什么它不在这种情况下。

回答

27

还有一个答案:-)它看起来像你得到这种行为,因为控制器加载视图的懒惰。该视图不会立即加载,它在第一次调用view访问器时被加载。因此,当您收到awakeFromNib时,NIB加载过程完成,但不适用于您的视图内的对象。看到这个代码:

@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); 
} 

这将记录:

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

但是,如果您强行加载视图:

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

日志变成这样:

#3: 1 
#1: 1 
+0

谢谢Zoul,这很有趣。我想我只是使用viewDidLoad更好,因为强制视图首先加载调用。我也读过使用awakeFromNib可能不是iPhone上的好主意,但似乎对此有不同看法。再次感谢... – fuzzygoat 2010-04-28 19:06:19

+0

如果您无权访问视图,请执行awaSeFromNib中的performSelector:withObject:delay调用。黑客,但有效。 – phatmann 2013-04-02 22:39:28

+0

第一次偶然发现了这个问题和答案 - 如果我早点发现它,它会为我节省很多麻烦!这个问题在2013年仍然存在,我相信这种行为与文档相矛盾 - 请参见:http://stackoverflow.com/questions/17400547/awakefromnib-outlets-and-storyboards-is-the-documentation-wrong – 2013-07-01 10:44:58

-1

确定对象不是nilNSAssertNSParameterAssert是你的朋友:

-(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]; 
} 

如果对象是真正初始化,尝试登录他们的地址,并确保出现在viewDidLoad的情况是一样的那些awakeFromNib

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

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

如果数字相同,您可以创建一个类别来设置setBackgroundColor上的断点,并在堆栈跟踪中查看发生了什么:

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

您可以使用自定义的子类做同样的伎俩:

@interface PeekingView : UIImageView {} 
@end 

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

现在设置你的UIViewObject在界面生成器是PeekingView类的,当有人试图设置背景,你就会知道。这应该捕捉到在初始化awakeFromNib中的视图后有人覆盖背景更改的情况。

但我认为问题会更简单,即。 imageView最有可能是nil

+0

嗨Zoul,大加赞赏,我将通过您的建议,第一件事就是在早上和让你知道我如何继续。你可能对这件事很简单,让我看看更好。 – fuzzygoat 2010-04-27 21:24:03

+0

嗨Zoul,控件确实为零,(请参阅上面的Edit_002) – fuzzygoat 2010-04-28 11:00:32

1

我相信你对super的调用需要是awakeFromNib方法的第一行,否则元素将不会被设置。

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

这是一个很好的猜测,应该确实先调用'super',但在这种情况下它不起作用。 – zoul 2010-04-28 16:50:38

0

我知道,这篇文章有点老,但我最近有过一个类似的问题,并希望与你分享它的解决方案。

有了NSTextView的子类,我想以交替顺序显示行颜色。为了能够从外部改变颜色,我添加了两个实例瓦尔我的子类,XNSStripedTableView:

@interface XNSStripedTableView : NSTableView { 

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

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

@end 

覆写highlightSelectionInClipRect:开了窍设置正确的颜色各clipRect。

- (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]; 

}

唯一的问题现在是,在哪里设置用于令pColor和sColor的初始值?我尝试了awakeFromNib:,但这会导致调试器出现错误。所以我用NSLog挖掘了这个问题:并找到了一个简单但可行的解决方案:在viewWillDraw中设置初始值:。由于第一次创建对象时没有调用该方法,因此我必须检查

- (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]; 

}

我认为这个解决方案是相当不错的:-)虽然人们可以重新选择令pColor和sColor的名字可以被调整为更“人类可读”。

-1

如果您使用的是UIView子类,而不是一个UIViewController子类,则可以覆盖loadView方法:

- (void)loadView 
{ 
    [super loadView]; 
    //IBOutlets are not nil here. 
}