2010-04-27 5 views
8

J'ai essayé de définir une couleur d'arrière-plan UIImageView (voir ci-dessous) dans awakeFromNibAccéder à Afficher dans awakeFromNib?

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

Quand il ne fonctionne pas, je me suis aperçu que son probablement parce que la vue n'a pas encore chargé et je dois déplacer le changement de couleur pour voirDidLoad.

Puis-je vérifier juste que j'ai ce droit?

gary

EDIT_002:

Je viens de commencer un nouveau projet pour vérifier à partir d'un démarrage propre. Je configure la vue de la même manière que je le fais toujours. Les résultats sont que les contrôles sont bien définis sur (null) dans awakeFromNib. Voici ce que j'ai:

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

SORTIE:

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

Je serais intéressé de savoir si cela devrait fonctionner, à partir de la documentation, il semble que cela devrait, mais étant donné la façon dont je mettre les choses en général je ne peux pas tout à fait comprendre pourquoi cela ne fonctionne pas dans ce cas.

Répondre

27

Une réponse supplémentaire :-) Il semble que vous obtenez ce comportement parce que le contrôleur charge les vues paresseusement. La vue n'est pas chargée immédiatement, elle est chargée la première fois que quelqu'un appelle l'accesseur view. Par conséquent, au moment où vous recevez awakeFromNib le processus de chargement NIB est terminé, mais pas pour les objets à l'intérieur de vos vues. Voir ce code:

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

Cette consigne:

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

Mais si vous force charger la vue:

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

Les modifications du journal dans ce:

#3: 1 
#1: 1 
+0

Merci Zoul, c'est très intéressant. Je suppose que je ferais mieux d'utiliser viewDidLoad en forçant la vue à charger les appels d'abord de toute façon.J'ai aussi lu qu'utiliser awakeFromNib n'est peut-être pas une bonne idée sur l'iPhone, mais il semble y avoir une opinion mitigée à ce sujet. Merci encore ... – fuzzygoat

+0

Si vous n'avez pas accès à la vue, alors effectSelector: withObject: delay appel de awakeFromNib. Un hack, mais efficace. – phatmann

+0

J'ai juste trébuché sur cette question et répondu pour la première fois - cela m'aurait sauvé un tas de problèmes si je l'avais trouvé plus tôt! Le problème existe toujours en 2013, et je crois que le comportement contredit la documentation - voir ici: http://stackoverflow.com/questions/17400547/awakefromnib-outlets-and-storyboards-is-the-documentation-wrong –

-1

Etes-vous sûr que les objets ne sont pas nil? NSAssert ou NSParameterAssert sont vos amis:

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

Si les objets sont vraiment initialisés, essayez de vous connecter leur adresse et assurez-vous que les instances qui apparaissent dans viewDidLoad sont les mêmes que ceux awakeFromNib:

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

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

Si les numéros sont les mêmes, vous pouvez créer une catégorie pour définir un point d'arrêt sur setBackgroundColor et jeter un coup d'œil dans la trace de la pile pour voir ce qui se passe:

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

Vous pouvez faire la même astuce en utilisant une sous-classe personnalisée:

@interface PeekingView : UIImageView {} 
@end 

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

Maintenant, vous allez définir votre UIViewObject pour être de classe PeekingView dans l'Interface Builder et vous saurez quand quelqu'un essaie de mettre en arrière-plan. Cela devrait intercepter le cas où quelqu'un écrase les modifications d'arrière-plan après l'initialisation de la vue dans awakeFromNib.

Mais je présume que le problème sera beaucoup plus simple, à savoir. imageView est très probablement nil.

+0

Salut Zoul, très apprécié, je vais passer par vos suggestions première chose le matin et laisser vous savez comment je m'entends. Vous avez probablement raison d'être quelque chose de simple, laissez-moi jeter un meilleur coup d'oeil. – fuzzygoat

+0

Salut Zoul, les contrôles étaient en effet nuls, (Voir Edit_002 ci-dessus) – fuzzygoat

1

Je crois que votre appel à super doit être la première ligne de la méthode awakeFromNib, sinon les éléments ne seront pas encore configurés.

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

C'est une bonne supposition et 'super' devrait en effet être appelé en premier, mais cela n'aide pas dans ce cas. – zoul

0

Je sais, ce post est un peu plus ancien, mais j'ai récemment eu un problème similaire et souhaite partager sa solution avec vous. Ayant sous-classé NSTextView, je voulais afficher les couleurs des lignes dans les ordres alternés. Pour être en mesure de modifier les couleurs de l'extérieur, j'ai ajouté deux instances vars à ma sous-classe, XNSStripedTableView:

@interface XNSStripedTableView : NSTableView { 

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

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

@end 

Ecrasement highlightSelectionInClipRect: le tour est joué pour définir la couleur correcte pour la clipRect respective.

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

}

Le seul problème est maintenant, où définir les valeurs initiales pour pcolor et sColor? J'ai essayé awakeFromNib:, mais cela causerait une erreur au débogueur. J'ai donc creusé le problème avec NSLog: et j'ai trouvé une solution simple mais viable: définir les valeurs initiales dans viewWillDraw:. Comme les objets ne sont pas créés en appelant la méthode la première fois, j'ai dû vérifier .

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

}

Je ne pense cette solution est tout à fait agréable :-) bien que l'on peut sélectionner à nouveau les noms des pcolor et sColor pourraient être ajustées pour être plus « lisible ».

-1

Si vous utilisez une sous-classe UIView au lieu d'une sous-classe UIViewController, vous pouvez remplacer loadView méthode:

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