Доступ к представлению в awakeFromNib? - PullRequest
10 голосов
/ 27 апреля 2010

Я пытался установить цвет фона UIImageView (см. Ниже) в awakeFromNib

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

Когда это не сработало, я понял, что это возможно, потому что представление еще не загружено, и я должен переместить изменение цвета в viewDidLoad.

Могу ли я просто подтвердить, что у меня есть это право?

1008 * Гэри *

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 ]

29 голосов
/ 28 апреля 2010

Еще один ответ :-) Похоже, вы получаете это поведение, потому что контроллер загружает представления лениво. Представление не загружается сразу, оно загружается при первом вызове метода доступа 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
1 голос
/ 27 апреля 2010

Я считаю, что ваш вызов super должен быть первой строкой в ​​методе awakeFromNib, иначе элементы еще не будут настроены.

-(void)awakeFromNib {
  [super awakeFromNib];
  [imageView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]];
  [testLabel setText:@"Pants ..."];  
}
0 голосов
/ 19 июля 2016

Если вы используете подкласс UIView вместо подкласса UIViewController, вы можете переопределить loadView метод:

- (void)loadView
{
    [super loadView];
    //IBOutlets are not nil here.
}
0 голосов
/ 15 февраля 2012

Я знаю, этот пост немного старше, но у меня недавно была похожая проблема, и я хотел бы поделиться с вами ее решением.

Имея подкласс 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: . Поскольку объекты не создаются при первом вызове метода, мне пришлось проверить 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];

} * * тысяча двадцать-один

Я думаю, что это решение довольно неплохо :-), хотя можно было бы повторно выбрать имена pColor, а sColor можно было бы настроить так, чтобы они были более «удобочитаемыми для человека».

0 голосов
/ 27 апреля 2010

Вы уверены, что объекты не 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...