iPhone SDK: яка різниця між loadView та viewDidLoad?


136

Працюючи з переглядами та контролерами перегляду в додатку для iPhone, чи може хтось пояснити різницю між loadView та viewDidLoad?

Мій особистий контекст полягає в тому, що я будую всі свої погляди з коду, я не використовую і не буду використовувати Інструмент інтерфейсу, якщо це має значення.

Я виявив, що часто, коли я додаю код init до loadView, я закінчую нескінченним слідом стека, тому я, як правило, виконую все будівництво дитячого перегляду в viewDidLoad ... але мені справді незрозуміло, коли кожен виконується, і куди більш підходяще місце для введення коду init. Що було б ідеально, це проста схема ініціалізації викликів.

Дякую!

Відповіді:


200

Я можу здогадатися, яка тут може бути проблема, тому що я це зробив:

Я виявив, що часто, коли я додаю код init до loadView, я закінчую нескінченний слід стека

Не читайте self.view в -loadView. Тільки встановіть його, не зрозумійте .

Доступ до властивості self.view викликає -loadView, якщо представлення не завантажено в даний час. Там ваша нескінченна рекурсія.

Звичайний спосіб побудувати подання програмно в -loadView, як це демонструється в прикладах Apple, призначених для попереднього інтерфейсу, виглядає приблизно так:

UIView *view = [[UIView alloc] init...];
...
[view addSubview:whatever];
[view addSubview:whatever2];
...
self.view = view;
[view release];

І я не звинувачую вас у тому, що ви не використовуєте ІБ. Я дотримувався цього методу для всієї Instapaper і вважаю себе набагато комфортнішим, ніж мати справу зі складностями IB, химерністю інтерфейсів та несподіваною поведінкою за кадром.


а-а-а, дякую за пояснення, нарешті! Я ухилився від ідіоми виділення тимчасової змінної, потім налаштування на самоперегляд, потім вивільнення ... це здавалося якось незручним, непотрібним. Зараз я можу зрозуміти, чому це рішення призвело би мене до того шляху, де я зараз опиняюся.
ryan.scott

У мене такий код і рекурсії немає. чому? -(void) loadView { // Frame for Hypnosis view CGRect frame = [[UIScreen mainScreen] bounds]; // Create a Hipnosis view v = [[HypnosisView alloc] initWithFrame:frame]; self.view = v;
користувач2054339

44

loadViewце метод, UIViewControllerякий фактично завантажить представлення і призначить його viewвластивості. Це також місце, яке підклас UIViewControllerзмінює, якщо ви хочете програмно налаштувати viewвластивість.

viewDidLoad- це метод, який викликається після завантаження перегляду. Це викликається після виклику loadView. Це місце, де ви можете перекрити і вставити код, який робить подальше початкове налаштування подання після його завантаження.


14
viewDidLoad()

використовуватиметься під час завантаження вашого перегляду з НІБ і хочете виконати будь-яку настройку після запуску

LoadView()

застосовується, коли ви хочете програмно створити свій погляд (без використання Interface Builder)


У цьому може бути якась проблема. У мене є тест, коли мій контролер перегляду не асоціювався з файлом NIB, viewDidLoad все ще називається
ruandao

11

Просто додайте кілька прикладів коду, щоб продемонструвати те, що сказав NilObject:

- (void)loadView
{
    // create and configure the table view
    myTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStyleGrouped];   
    myTableView.delegate = self;
    myTableView.dataSource = self;
    myTableView.scrollEnabled = NO;
    self.view = myTableView;

    self.view.autoresizesSubviews = YES;
}

- (void)viewDidLoad 
{
  self.title = @"Create group";

  // Right menu bar button is to Save
  UIBarButtonItem *saveButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(save)];
  self.navigationItem.rightBarButtonItem = saveButtonItem;
  [saveButtonItem release];
}

4
тож між вами двома, чи точно сказати, що loadView - це те, де я повинен зробити аллок / ініт самостійного перегляду мого контролера, а дочірні подання повинні оброблятися у viewDidLoad (або пізнішій версії)?
ryan.scott

2

Щоб запобігти нескінченному циклу, коли ви читаєте self.view, викликайте суперреалізацію класу під час завантаження представлення. Суперреалізація виділить для вас новий UIView.

- (void) loadView {
[super loadview];

// init code here...

[self.view addSubView:mySubview1]; //etc..

}

6
Я можу присягнути, що документація Apple сказала, що вам не потрібно телефонувати [super loadView];. Це було суперечить в прикладах, але я думаю, що документи сказали це правильно (я знайшов численні помилки в прикладах з часом). [super loadView]потрібен для UITableViewController тощо. Однак! Будь-яка установка після завантаження (наприклад, додавання додаткових підпрезмінок) повинна виконуватися в viewDidLoad.
Іван Вучиця

Я поки що телефонував [super loadView] без побічних ефектів. Це може бути правдою, якщо ви маєте намір встановити self.view на те, що ви зробили самі.
futureelite7

Якщо ви зателефонуєте [super loadView] всередині loadView, він спробує завантажити представлення з віконця, якщо це можливо, з ім'ям за замовчуванням. Тому потрібно бути обережним.
Ian1971

І якщо ви зателефонуєте [super loadView], ви ініціалізуєте self.view методом super loadView
Олексій Назарський

1

Найпростіший спосіб використання loadView - це зробити якийсь тип контролера базового перегляду, наприклад MyBaseViewController, який є підкласом UIViewController. У його методі loadView створити подання таким чином:

-(void) loadView {
    if ([self viewFromNib]) {
        self.view = [self viewFromNib];
    } else {
        self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    }
    self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
    self.view.backgroundColor = [UIColor whiteColor];
}

І коли вам потрібно зробити якийсь контролер перегляду, ви просто використовуєте підклас MyBaseViewController, і в його контролері loadView ви просто викликаєте [super loadView], як це

//sucblass loadView
-(void) loadView {
    [super loadView];

    //rest of code like this..
    UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];
    [self.view addSubview:myLabel];
    [myLabel release];
}

1

loadView()викликається, коли ваш контролер попросить створити його self.view. Ви можете зробити це самостійно, як

self.view = [UIView alloc] init...];

Або батьківський клас UIController вашого контролера вже має ім'я методу, -loadView()який ініціалізує ваш self.view в порожній вигляд. Тоді ви можете зателефонувати

[super loadView];

Я дуже рекомендую другий підхід, оскільки він заохочує спадщину. Тільки якщо ваш контролер перегляду безпосередньо не успадковується від UIViewController.


0

Визначення, яке Apple дало на viewDidLoad, згадувало, що воно викликається після того, як подання контролера завантажується в пам'ять. Простіше кажучи, це перший метод, який завантажиться.

Ви можете задуматися, при яких умовах цей метод буде повністю використаний? Відповідь, в основному все, що ви хотіли, щоб додаток завантажувався спочатку. Наприклад, ви можете мати інший колір фону, а не білий, ви можете вибрати синій.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.