2014-03-06 39 views
34

對不起,但這本身可能不是一個編程問題,而更多的是關於iOS生命週期功能性質的問題。iOS 7 - viewDidLoad和viewDidAppear之間的區別

我有一個應用程序,我有一個函數創建四個數組並通過數據庫查詢填充它們。起初,我從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]; 

} 

然而,當我部署了這一點,沒有任何延遲,使得activityIndi​​catorView沒用。

我的問題是,爲什麼在我看來,viewDidLoadviewDidAppear之間存在「性能差異」?

+0

您的方法'initializeArrays'是否在單獨的線程中進行初始化?如果沒有,那麼你不會得到動畫。 – ThomasW

+0

我不這麼認爲。我沒有明確實現多線程。 – Razgriz

+0

當您調用'viewDidLoad'時,可能會有很多事情正在進行,這會導致延遲。你可以用「viewDidAppear」加載你的VC。這將允許您在後臺任務未執行時執行任何操作。 –

回答

210

請按照下面的視圖控制器生命週期每次。您將以這種方式對您的應用程序的編碼和性能感到驚訝。如果主線程(UI線程)不旺

enter image description here

+2

漂亮的圖形 - 你在哪裏得到它?我可能想用這個,我想引用你的來源。 – NSProgrammer

+2

我通過google找到它。使用這個流程真的很酷。如果你喜歡這個答案,不要忘記加註。 – 2014-03-06 04:56:39

+2

btw,'viewDidUnload'在iOS6中已被棄用 –

1

但是,當您從服務器(或大量數據處理)加載內容時,還必須考慮延遲。你如果把你所有的網絡通信到viewDidLoad中viewWillAppear中,他們將執行用戶獲取查看視圖之前 - 這可能導致你的應用程序的短凍結。首先向用戶顯示帶有某種活動指示符的未填充視圖可能是個好主意。當您完成網絡連接時,可能需要一兩秒鐘(甚至可能會失敗 - 誰知道?),您可以使用數據填充視圖。各種嘰嘰喳喳客戶都可以看到關於如何做到的好例子。例如,當您在Twitterrific中查看作者詳細信息頁面時,該視圖只會在網絡查詢完成之前顯示「正在加載...」。

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

+0

viewDidLoad不會調用一次基於你的視圖控制器初始化 – NSProgrammer

+0

我上面說過的同樣的事情,在tabbarcontroller當你初始化和添加VC在tabbar然後他們調用viewdidload但是當你點擊tabbar viewdidload中的標籤不是調用。 –

+0

@NSProgrammer你可以解釋一下哪個視圖控制器初始化你每次調用viewDidLoad –

1

activityIndicatorViews只會動畫。 viewDidLoad:viewDidAppear:都在主線程上執行。如果如您所提到的,initializeArrays方法不會在單獨的線程中執行,那麼activityIndicatorViews將永遠沒有時間進行動畫製作。

4

我打算向您指出Apple的文檔,因爲我認爲需要更多關於View Controller生命週期的解釋,而不僅僅是將問題回答爲短語。

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

最終,你的視圖控制器都有一個生命週期:

初始化 - 無論你初始化你的視圖控制器

viewWillLoad/viewDidLoad中 - 當視圖構造(通過第一個電話叫通過它的視圖屬性檢索視圖控制器的UIView - 也稱爲延遲加載)

viewWillAppear: - 當視圖正準備立即顯示(動畫==否)或查看過渡(動畫== YES)

viewDidAppear: - 如果視圖外觀未取消和視圖控制器的視圖完全出現

viewWillDisappear: - 補充viewWillAppear中:

viewDidDisappear: - 補充viewDidAppear:

viewWillUnload/viewDidUnload - 視圖時卸載由於內存限制(不用擔心這些了)

的dealloc棄用的API - 視圖控制器本身正在被釋放

儘管如此,我相信你的問題可能是你的數組初始化阻塞了主線程。你應該閱讀了關於異步編程但在此期間,你可以做這樣的事情:

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

有viewDidLoad中絕對沒有性能上的差異:和viewDidAppear :.兩者都是在主線程上運行的正常功能。如果您的initializeArrays方法需要3秒加載,無論您調用哪種方法,都需要3秒。由於您沒有明確地更改線程,因此您調用initializeArrays的任何函數在完成之前都不會退出。

對[self.activityIndi​​catorView startAnimating]的調用將基本上「標記」activityIndi​​catorView,以便主線程上的另一個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]; 
} 
0

查看有沒有加載 - 第一種方法,當視圖加載第一次,但沒有出現在屏幕/窗口,只加載時調用。

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

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

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

**

  • 查看生命週期

**

1)viewDidLoad中(稱爲僅當視圖被加載第一次),則 2)viewWillAppear中(將被稱爲次數),然後 3)ViewDidAppear(將被稱爲次數),然後 4)ViewWillDisAppear(將被稱爲次數),然後 5)ViewDidD isAppear(將被稱爲次數)