Вопрос:

iOS 7 - разница между viewDidLoad и viewDidAppear

ios objective-c

53275 просмотра

7 ответа

3898 Репутация автора

Извините, но это может быть не программный вопрос как таковой, а скорее вопрос природы функций жизненного цикла iOS.

У меня есть приложение, где у меня есть функция, которая создает четыре массива и заполняет их с помощью запросов к базе данных. Сначала я вызывал функцию из viewDidLoadфункции, однако всякий раз, когда представление загружается, требуется время (около 3-4 секунд), прежде чем представление действительно появится. Так что я сделал, я создал, activityViewIndicatorи моя viewDidLoadфункция выглядит примерно так:

- (void)viewDidLoad:(BOOL)animated{
    [super viewDidLoad];

    NSLog(@"viewDidLoad Entered");
    [self.activityIndicatorView startAnimating];

    partInput.delegate = self;
    brandInput.delegate = self;
    barcodeInput.delegate = self;
    itemNameInput.delegate = self;

    //initializeArrays is the function that initializes the arrays
    [self initializeArrays];

    [self.activityIndicatorView stopAnimating];

}

Однако это не работает, так как viewDidLoadфункция срабатывает, когда приложение все еще находится в предыдущем представлении. Вид отображается только после того, viewDidLoadкак он уже сделан. Вместо этого я переместил инициализацию массива в мою viewDidAppearфункцию, которая выглядит следующим образом:

- (void)viewDidAppear:(BOOL)animated{
    NSLog(@"viewDidAppear loaded successfully");
    [self.activityIndicatorView startAnimating];

    partInput.delegate = self;
    brandInput.delegate = self;
    barcodeInput.delegate = self;
    itemNameInput.delegate = self;

    [self initializeArrays];

    [self.activityIndicatorView stopAnimating];

}

Однако, когда я развернул это, не было никакой задержки, что делало ActivityIndicatorView бесполезным.

Мой вопрос: почему мне кажется, что есть разница в производительности между viewDidLoadи viewDidAppear?

Автор: Razgriz Источник Размещён: 06.03.2014 04:19

Ответы (7)


1 плюс

3316 Репутация автора

Однако, когда вы загружаете вещи с сервера (или интенсивную обработку данных), вы также должны думать о задержке. Если вы упакуете все свои сетевые коммуникации в viewDidLoad или viewWillAppear , они будут выполнены до того, как пользователь увидит представление - возможно, в результате произойдет короткое замораживание.вашего приложения. Это может быть хорошей идеей, чтобы сначала показать пользователю незаселенный вид с каким-либо индикатором активности. Когда вы закончите работу с сетью, что может занять секунду или две (или может даже потерпеть неудачу - кто знает?), Вы можете заполнить представление своими данными. Хорошие примеры того, как это можно сделать, можно увидеть в различных клиентах Twitter. Например, когда вы просматриваете страницу сведений об авторе в Twitterrific, в представлении отображается только «Загрузка ...», пока сетевые запросы не будут выполнены.

ViewDidLoad вызывает только один раз, когда вы инициализируете свой ViewController, но Viewdidapper вызывает каждый раз.

Автор: Pandey_Laxman Размещён: 06.03.2014 04:28

229 плюса

0 Репутация автора

Решение

Пожалуйста, следуйте приведенным ниже инструкциям. Таким образом, вы будете поражены кодированием и производительностью вашего приложения.

введите описание изображения здесь

Автор: user2223516 Размещён: 06.03.2014 04:41

1 плюс

14628 Репутация автора

Анимация activityIndicatorViewsбудет выполняться только в том случае, если основной поток (поток пользовательского интерфейса) не занят. viewDidLoad:и viewDidAppear:оба выполняются в главном потоке. Если, как вы упомянули, initializeArraysметод не выполняется в отдельном потоке, он activityIndicatorViewsникогда не будет иметь времени для анимации.

Автор: ThomasW Размещён: 06.03.2014 04:42

4 плюса

2108 Репутация автора

Я собираюсь указать вам на документы Apple, потому что я думаю, что нужно более подробное объяснение жизненного цикла View Controller, чем просто ответить на ваш вопрос в формулировке.

https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html

В конечном счете, ваш контроллер представления имеет жизненный цикл:

init - однако вы инициализируете свой контроллер представления

viewWillLoad / viewDidLoad - вызывается при построении представления (через первый вызов, чтобы получить UIView контроллера представления через его свойство view - иначе говоря, ленивая загрузка)

viewWillAppear: - когда представление готовится к немедленному отображению (анимированный == НЕТ) или просмотру перехода (анимированный == ДА)

viewDidAppear: - если вид представления не был отменен, и вид контроллера представления полностью появляется

viewWillDisappear: - дополняет viewWillAppear:

viewDidDisappear: - дополняет viewDidAppear:

viewWillUnload / viewDidUnload - устаревшие API, когда представление выгружается из-за ограничений памяти (не беспокойтесь об этом больше)

dealloc - сам контроллер представления освобождается

В конце концов, я полагаю, что ваша проблема может заключаться в том, что вы блокируете основной поток при инициализации массива. Вы должны прочитать об асинхронном программировании, но тем временем вы можете сделать что-то вроде этого:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // other stuff

    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        typeof(weakSelf) strongSelf = weakSelf;
        if (strongSelf) {
            [strongSelf initializeArraysSynchronously];
            dispatch_async(dispatch_get_main_queue(), ^{
                strongSelf.doneIntializingArrays = YES;
                [strongSelf.activityIndicatorView stopAnimating];
            });
        }
    });
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    if (!self.doneInitializingArrays) {
        [self.activityIndicatorView startAnimating];
    } 
}
Автор: NSProgrammer Размещён: 06.03.2014 04:49

2 плюса

1493 Репутация автора

Нет абсолютно никакой разницы в производительности между viewDidLoad: и viewDidAppear :. Обе нормальные функции, работающие в главном потоке. Если ваш метод initializeArrays загружается за 3 секунды, он займет 3 секунды в зависимости от того, какой метод вы вызываете. Поскольку вы не меняете явно потоки, любая функция, в которой вы вызываете initializeArrays, не завершится, пока не будет завершена.

Вызов [self.activityIndicatorView startAnimating] в основном «помечает» активность ActivityIndicatorView, так что другая функция пользовательского интерфейса в основном потоке начнет его анимацию. (Вот почему важен основной поток или поток «пользовательский интерфейс», потому что все анимации и визуальные обновления экрана координируются на нем). Таким образом, функция, которая фактически запустит активность ActivityIndicator, не будет вызываться до тех пор, пока initializeArrays не будет завершен, и вы уже вызвали «stopAnimating».

Попробуй это:

- (void)viewDidLoad:(BOOL)animated{
    [super viewDidLoad];

    NSLog(@"viewDidLoad Entered");
    [self.activityIndicatorView startAnimating];

    partInput.delegate = self;
    brandInput.delegate = self;
    barcodeInput.delegate = self;
    itemNameInput.delegate = self;
}

- (void)viewDidAppear:(BOOL)animated{
    //initializeArrays is the function that initializes the arrays
    [self initializeArrays];
    [self.activityIndicatorView stopAnimating];
}
Автор: devdavid Размещён: 06.03.2014 04:58

1 плюс

437 Репутация автора

View Did Load - Первый метод, который вызывается, когда представление загружается впервые, но не отображается на экране / окне, только загружается.

вызывается только один раз, когда представление загружается впервые.

View Did Appear - После вызова viewWillAppear будет вызван viewDidAppear. Это означает, что вид теперь появляется на экране.

Вызывается количество раз, когда пользователь перемещается из этого контроллера вида в другой контроллер представления и возвращается.

**

  • Посмотреть жизненный цикл

**

1) ViewDidLoad (вызывается только при первой загрузке представления), затем 2) ViewWillAppear (будет вызываться несколько раз), затем 3) ViewDidAppear (будет вызываться несколько раз), затем 4) ViewWillDisAppear (будет вызываться числом раз), затем 5) ViewDidDisAppear (будет вызываться количество раз)

Автор: Anubhav Giri Размещён: 22.01.2016 07:56

0 плюса

3612 Репутация автора

Для тех, кто программирует программно (без Interface Builder), loadViewэто первый доступный метод жизненного цикла, viewDidLoadи программная разработка часто использует его loadViewбольше viewDidLoad, поэтому имейте это в виду. Часть того, что делает IB, это написать loadViewдля вас. IB - это просто способ сократить программную разработку, но если вы хотите лучше понять Cocoa Touch, вы должны понимать это программно.

loadViewна первом месте, и именно там обычно создаются элементы пользовательского интерфейса, включая представление самого контроллера представления (которое должна явно создавать программная разработка). Ограничения могут быть добавлены здесь, но они не обрабатываются до более поздних этапов жизненного цикла.

viewDidLoad где «логика» обычно создается после того, как установлены элементы пользовательского интерфейса.

viewWillAppearи viewWillLayoutSubviewsвызываются следующим прямо перед тем, как сам интерфейс должен создать себя.

viewDidLayoutSubviewsВызывается следующим и может вызываться несколько раз на одном контроллере представления, прежде чем он действительно появится. Здесь применяется автоматическое расположение. Это также, где программист может получить значения безопасной области представления, так как они не доступны до этого метода.

viewDidAppear идет последним после того, как представление контроллера представления появилось в иерархии представления.

Автор: bsod Размещён: 29.08.2018 04:06
Вопросы из категории :
32x32