簡體   English   中英

iOS 7 - viewDidLoad和viewDidAppear之間的區別

[英]iOS 7 - Difference between viewDidLoad and viewDidAppear

對不起,這可能不是一個編程問題本身,而是更多關於iOS生命周期功能的性質的詢問。

我有一個應用程序,我有一個函數創建四個數組並通過數據庫查詢填充它們。 首先,我從viewDidLoad函數調用該函數,但是,每當加載View時,在視圖實際出現之前需要花費時間(大約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];

}

但是,當我部署它時,沒有任何延遲,使activityIndi​​catorView無用。

我的問題是,為什么我認為viewDidLoadviewDidAppear之間存在“性能差異”?

請每次按照以下查看控制器生命周期。 您將以這種方式對應用程序的編碼和性能感到驚訝。

在此輸入圖像描述

我將指向Apple的文檔,因為我認為需要對View Controller生命周期進行更多解釋,而不僅僅是回答你的問題。

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

最終,您的視圖控制器具有生命周期:

init - 但是您初始化視圖控制器

viewWillLoad / viewDidLoad - 在構造視圖時調用(通過第一次調用通過它的視圖屬性檢索視圖控制器的UIView - 也稱為延遲加載)

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

viewDidLoad:和viewDidAppear:之間絕對沒有性能差異。 兩者都是在主線程上運行的普通函數。 如果你的initializeArrays方法加載需要3秒鍾,那么無論你調用哪種方法都需要3秒。 由於您沒有顯式更改線程,因此調用initializeArrays的任何函數在完成之前都不會退出。

對[self.activityIndi​​catorView startAnimating]的調用將基本上“標記”activityIndi​​catorView,以便主線程上的另一個UI函數將啟動它的動畫。 (這就是主要或'UI'線程很重要的原因,因為屏幕上的所有動畫和視覺更新都是相互協調的)。 因此,實際獲取activityIndi​​cator的函數不會被調用,直到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];
}

但是,當您從服務器(或繁重的數據處理)加載東西時,您還必須考慮延遲。 如果將所有網絡通信打包到viewDidLoadviewWillAppear中 ,它們將在用戶看到視圖之前執行 - 可能導致應用程序的短暫凍結 首先向用戶顯示具有某種活動指示符的未填充視圖可能是個好主意。 當您完成網絡時,可能需要一兩秒鍾(或者甚至可能會失敗 - 誰知道?),您可以使用您的數據填充視圖。 在各種Twitter客戶端中可以看到關於如何做到這一點的好例子。 例如,當您在Twitterrific中查看作者詳細信息頁面時,視圖僅顯示“正在加載...”,直到網絡查詢完成。

ViewDidLoad只在您初始化ViewController但每次調用Viewdidapper時調用一次。

僅當主線程(UI線程)不忙時, activityIndicatorViews才會生成動畫。 viewDidLoad:viewDidAppear:都在主線程上執行。 如上所述,如果initializeArrays方法不在單獨的線程中執行,那么activityIndicatorViews將永遠沒有時間進行動畫處理。

View Did Load - 第一種方法,在第一次加載視圖但在屏幕/窗口上沒有出現時調用,僅加載。

只在第一次加載視圖時調用一次。

查看已顯示 - 在調用viewWillAppear后,將調用viewDidAppear。 這意味着視圖現在出現在屏幕上。

用戶從該視圖控制器移動到另一個視圖控制器並返回時調用的次數。

**

  • 查看生命周期

**

1)ViewDidLoad(僅在第一次加載視圖時調用),然后2)ViewWillAppear(將被調用次數),然后3)ViewDidAppear(將被調用次數),然后4)ViewWillDisAppear(將被調用的數量為次),然后5)ViewDidDisAppear(將被調用次數)

對於那些以編程方式編碼的(沒有Interface Builder), loadView是第一個可用的生命周期方法,而不是viewDidLoad ,而編程開發通常比viewDidLoad更多地使用loadView ,所以請記住這一點。 IB所做的一部分是為您編寫loadView IB只是一種縮短程序開發的方法,但如果你想最好地理解Cocoa Touch,你應該以編程方式理解它。

loadView是第一個,通常是創建UI元素的地方,包括視圖控制器本身的視圖(編程開發必須明確創建)。 可以在此處添加約束,但直到生命周期的后期才會處理它們。

viewDidLoad是在建立UI元素后通常進行“邏輯”的地方。

viewWillAppearviewWillLayoutSubviews在UI本身構建自身之前被調用。

viewDidLayoutSubviews被調用next,可以在實際出現之前在同一個視圖控制器上多次調用。 這是應用自動布局的地方。 這也是程序員可以獲取視圖的安全區域值的地方,因為在此方法之前它們不可用。

視圖控制器的視圖出現在視圖層次結構中后, viewDidAppear位於最后。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM