Доступ к представлению в awakeFromNib?
Я пытался установить цвет фона UIImageView (см. Ниже) в awakeFromNib
[imageView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]];
Когда это не сработало, я понял, что это возможно, потому что представление еще не загружено, и я должен переместить изменение цвета в viewDidLoad.
Могу ли я просто проверить, что у меня есть это право?
Гэри
EDIT_002:
Я только начал новый проект, чтобы проверить это с нуля. Я настраиваю вид так же, как всегда. В результате элементы управления действительно установлены в (null) в awakeFromNib. Вот что у меня есть:
КОД:
@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];
}
ВЫХОД:
awakeFromNib ...
myLabel: (null)
myView : (null)
viewDidLoad ...
myLabel: UILabel
myLabel: UIImageView
Мне было бы интересно узнать, должно ли это работать, из документов, которые выглядят так, как должно, но, учитывая то, как я обычно это настраиваю, я не совсем понимаю, почему это не так в этом случае.
5 ответов
Еще один ответ:-) Похоже, вы получаете такое поведение, потому что контроллер загружает представления лениво. Представление не загружается сразу, оно загружается при первом вызове 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
Я считаю, что ваш вызов super должен быть первой строкой в методе awakeFromNib, иначе элементы еще не будут настроены.
-(void)awakeFromNib {
[super awakeFromNib];
[imageView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]];
[testLabel setText:@"Pants ..."];
}
Я знаю, что этот пост немного старше, но у меня недавно была похожая проблема, и я хотел бы поделиться с вами ее решением.
Подклассифицировав 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 можно было бы настроить так, чтобы они были более "удобочитаемыми для человека".
Если вы используете подкласс UIView вместо подкласса UIViewController, вы можете переопределить loadView
метод:
- (void)loadView
{
[super loadView];
//IBOutlets are not nil here.
}
Вы уверены, что объекты не nil
? NSAssert
или же NSParameterAssert
ваши друзья:
-(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
,