1. 程式人生 > >IOS viewDidLoad方法被執行兩次(viewDidLoad和loadView方法詳解)

IOS viewDidLoad方法被執行兩次(viewDidLoad和loadView方法詳解)

為了搞清楚viewDidLoad、loadView等方法的用途和呼叫順序,寫了一個小demo,不料viewDidLoad方法被執行了兩次,模擬器也一直是黑屏。查看了這兩個方法的官方解釋後找到了錯誤原因和解決方法。

首先來看UIViewController.h檔案中對viewDidLoad方法的解釋:

- (void)viewDidLoad; 
// Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is
after the view is set.

接下來是對loadView方法的解釋:

- (void)loadView; 
// This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.

無論是從xib檔案中載入檢視,還是自己建立檢視,viewDidLoad方法都會被呼叫,而且都是在檢視已經被載入後呼叫,所以這裡可以明確的一點是,任何UI控制元件的建立都不應該在viewDidLoad方法中被實現,因為這是xib檔案或者loadView方法的任務。viewDidLoad只是通過nib或者loadView方法載入檢視的一週拓展和補充機制,比如一些不方便通過nib設定的屬性或是臨時需要進行處理的控制元件內容。

至於loadView方法和xib檔案的關係,個人的理解是:真正的UI控制元件的建立,都是要通過呼叫loadView中的程式碼來實現的,只不過在xib檔案中,這些程式碼以xml格式的文件被儲存,並且蘋果通過storyboard解析這個xml文件,形成了一個視覺化的圖形介面。這是兩者的共同點,至於不同點,官方文件中的解釋已經很清楚了,一旦呼叫了loadView方法就意味著不是用nib檔案。這就意味著loadView和xib檔案不相容。loadView具有更高的優先順序。

下面通過幾個實驗來證明以上觀點。
實驗1:
建立一個空的工程檔案,在viewDidLoad函式中寫入簡單的一行程式碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"123");
}

實驗結果:執行程式後發現:控制檯輸出一行結果“123”。模擬器顯示一個純白色的介面。
實驗分析:控制檯的結果非常容易理解。但是我們並沒有建立一個UIView或者設定它的背景顏色,系統是怎麼建立我們在模擬器中看到的內容的呢?
答案是,如果我們不實現loadView方法,系統會預設我們不適用自定義的方式建立view而是從nib檔案中載入。這時候就回去storyboard或者其他相應的nib檔案中去尋找載入檢視的程式碼。由於預設的ViewController類在main.storyboard中有自己的nib檔案,所以可以成功的載入一個UIView。

實驗2:
實現一個空的loadView方法:

- (void)loadView{
}

實驗結果:執行程式後發現,控制檯輸出兩行“123”,模擬器黑屏。
實驗分析:模擬器黑屏非常容易理解,因為我們實現了loadView方法,編譯器以為我們要自定義一個UIView物件,從而去執行loadView方法中的程式碼,試圖建立一個UIView,但是顯然這樣做會失敗,所以得到一個黑色的(沒有任何內容)的介面。至於為什麼viewDidLoad方法會被呼叫兩次,原因並不清楚(希望讀到此處的大牛留言指教)。

實驗三:
實現完整的loadView方法:

- (void)loadView{
    self.view = [[ UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    self.view.backgroundColor = [UIColor whiteColor];
}

實驗結果:同實驗1的結果
實驗分析:實現了一個完整的UIView的建立過程,與通過nib檔案建立非常類似。

通過以上幾個實驗得出以下結論:
1.如果想要通過自定義的程式碼建立UIView,把這些程式碼都寫入loadView方法裡面去。
2.希望通過nib檔案建立UIView的話,不要重寫loadView方法。
3.viewDidLoad方法被執行兩次很有可能是重寫了一個不完整的loadView方法導致的 。

相關推薦

IOS viewDidLoad方法執行viewDidLoadloadView方法

為了搞清楚viewDidLoad、loadView等方法的用途和呼叫順序,寫了一個小demo,不料viewDidLoad方法被執行了兩次,模擬器也一直是黑屏。查看了這兩個方法的官方解釋後找到了錯誤原因和解決方法。 首先來看UIViewController.h檔

thinkphp中方法執行

       最近兩天程式碼中出現了一個問題,就是我的控制器的方法中執行了向資料庫插入,每次點開該頁面,add()方法就會被執行兩次,就是因為這個add方法讓我發現此方法被執行了兩次,因為每次點開該頁面,資料庫就會增加兩條記錄。    

支付寶面試題: 30秒內限制某方法呼叫100 一個時間段限制方法呼叫的次數

假設一個Class的方法 a,被限定30秒內只能被呼叫100次,如何實現。 當時沒答上,回來補上    1、定義呼叫介面Icallee public interface Icallee {public void play(); } 2、實現呼叫介面類 publi

spring定時任務執行的原因與解決方法

ref net 任務 article 服務 每次 bsp tail 本地 spring定時任務,本地執行一次,放到服務器上後,每次執行時會執行兩次,原因及解決辦法。 http://blog.csdn.net/yaobengen/article/details/70312

struts2,action方法自動執行

sys sele urn 自動 obj sel hiberna ron name 發現一個比較有意思的bug, //Action中以get開頭且返回類型不為void(如 public Object get*() )的方法會被自動執行//放入值棧時會執行一次,//若在頁面調

Android多程序app中Application回撥onCreate()方法執行分析及解決

最近工作中碰到一個問題,在優化app,使用DDMS檢視Application log過程中看到,app啟動了三個程序,一個主程序,兩個附帶的程序。如下圖可看到一個app啟動的三個程序。  自定義Application回撥方法onCreate()被執行了3次。開始不知是何原因。 相

Tomcat 啟動的問題(ServletContextListener的contextInitialized執行的問題)

問題:     在啟動 tomcat5 時,控制檯視窗會打印出兩行“hello word”字串? 問題原因:     因為hello應用本來就放在Tomat的預設webapp目錄下(tomcat在啟動時肯定會載入1次),然後又在server.xml中做了配置,為了達到訪問根就可以訪問hello應用

RadioGroup呼叫check(id)方法時,onCheckedChanged方法執行解決辦法

RadioGroup bottomMenuBar = (RadioGroup) findViewById(R.id.bottomMenuBar); bottomMenuBar.setOnCheckedChangeListener(this); bottomMenuBar.c

Java Web開發中,自定義過濾器執行的原因分析及解決辦法

本文出處:http://blog.csdn.net/chaijunkun/article/details/7646338,轉載請註明。由於本人不定期會整理相關博文,會對相應內容作出完善。因此強烈建議在原始出處檢視此文。 在Java Web開發過程中,我們可以使用過濾器和Sp

Android 經典筆記之一:setOnKeyListener方法事件執行

Android 經典總結案例一 目錄介紹: 1.完美解決onActivityResult提前執行呼叫的一系列問題 1.1 出現的問題 1.2 解決方案 1.3 相關原理說明 1.4 知識拓展 2.EditText呼叫軟鍵盤搜尋的setOnKeyListener方

Quartz每次排程時執行

[關鍵字:重複執行、重複呼叫、每次執行兩次、執行2次]前言: 先說一下,專案背景。由於組內某成員在用Maven搭建專案時不規範,導致專案的名稱與實際訪問專案名稱不一致。在部署專案時,必需要配一下虛擬路徑,對映到那個專案所在目錄下去,才能正常訪問。舉個例子:專案名稱叫student-web,部署到Tomcat

UI自動化測試瀏覽器操作及對元素的定位方法xpath定位css定位

cli 刷新 ota api enter 版本 ror apache 窗口 Selenium下的Webdriver工具支持FireFox(geckodriver)、 IE(InternetExplorerDriver)、Chrome(ChromeDriver)、 Opera

InnoDB的關鍵特性-插入快取,寫,自適應hash索引

InnoDB儲存引擎的關鍵特性包括插入緩衝、兩次寫(double write)、自適應雜湊索引(adaptive hash index)。這些特性為InnoDB儲存引擎帶來了更好的效能和更高的可靠性。插入緩衝插入緩衝是InnoDB儲存引擎關鍵特性中最令人激動的。不過,這個名字

自定義一個更好用的SwipeRefreshLayout彈力拉伸效果轉載

dsc drag 常數 lane swipe loading 數據改變 高中數學 tca 轉自: 自定義一個更好用的SwipeRefreshLayout(彈力拉伸效果詳解) 前言 熟悉SwipeRefreshLayout的同學一定知道,SwipeRefreshLayout是

CentOS6.5下Cloudera安裝搭建部署大數據集群圖文分五大步博主強烈推薦

centos6 數據 http 時間 log .com pos OS 客戶端  第一步: Cloudera Manager安裝之Cloudera Manager安裝前準備(CentOS6.5)(一) 第二步: Cloudera Manager安裝之時間服務器和

函數的特點,應用,重載等講解代碼加理論

學生 打印 ext 錯誤 如果 ron sta urn double 函數的特點:1、定義函數可以將功能代碼進行封裝2、便於對該功能進行復用3、函數只有被調用才會被執行4、函數的出現提高了代碼的復用性5、對於函數沒有具體返回值的情況,返回值類型用關鍵字void表示,那麽該函

SELECT is not allowed in cluster Redis叢集JedisCluster資料庫

(1)redis在單機模式下redis.conf配置檔案中預設的資料庫數量是16個,   # Set the number of databases. The default database is DB 0, you can select# a different one on

Linuxvi/vim命令使用

  vi test.txt 或者 vim test.txt 再或者 touch test.txt vim是vi的升級版,指令更多,功能更強。 下面是收集的vim用法,當在vim裡面要實現退出,首先要做的是按【Esc】,然後再輸入【:wq】 一、一般模式:

LNMP架構四php-fpm的配置

四、php-fpm的配置詳解      和LAMP不同的是,在LNMP架構中,php-fpm作為獨立的一個服務存在,既然是獨立服務,那麼它必然有自己的配置檔案。php-fpm的配置檔案為/usr/local/php-fpm/etc/php-fpm.conf,它同

物件-中6個預設函式

本文主要是對類的6個預設函式進行講解 類的預設成員函式有6個:建構函式                                                解構函式