iOS push頁面出現(xiàn)的卡頓假象,引申出的viewcontroller的和view的

  • 問題:從一個控制器push到另一個控制器時得湘,有時會出現(xiàn)卡頓的一種現(xiàn)象杖玲,如下
push卡頓假象.gif

測試代碼里什么數(shù)據(jù)都沒有加載,所以排除是卡頓原因淘正,view沒有漸變效果摆马,而是瞬間變換的,loadView里創(chuàng)建新的UIView后沒有設置背景色(默認是透明)臼闻,所以切換時會看到上一頁的內(nèi)容。
解決:push的下一頁面的self.view設置一個顏色就可以解決

  • 說到這里不免提下viewcontroller的生命周期問題

一囤采、ViewController結構

按結構可以對所有ViewController分成兩類:1述呐、主要用于展示內(nèi)容的ViewController,這種ViewController主要用于為用戶展示內(nèi)容蕉毯,并與用戶交互乓搬,如UITableViewController,UIViewController代虾。2进肯、用于控制和顯示其他ViewController的ViewController。這種ViewController一般都是一個ViewController的容器棉磨。如UINavigationController江掩,UITabbarController。它們都有一個屬性:viewControllers乘瓤。其中UINavigationController表示一種Stack式結構环形,push一個ViewController或pop一次,因此后一個ViewController一般會依賴前一個ViewController衙傀。而UITabbarController表示一個Array結構抬吟,各個ViewController是并列的。第一種ViewController會經(jīng)常被繼承差油,用來顯示不同的數(shù)據(jù)給用戶拗军。而第二種很少被繼承,除非你真的需要自定義它蓄喇。注:細心的同學應該能發(fā)現(xiàn)发侵,在Xcode中新建一個ViewController時,只可以選擇繼承自UIViewController和UITableViewController妆偏,而它們都是第一種刃鳄。

二、Controller和View的生命周期

這里指的View是指Controller的View钱骂。它作為Controler的屬性叔锐,生命周期在Controller的生命周期內(nèi)。就是說你的Controller不能在view釋放前就釋放了见秽。
圖2 ViewController生命周期

當你alloc并init了一個ViewController時愉烙,這個ViewController應該是還沒有創(chuàng)建view的。ViewController的view是使用了lazyInit方式創(chuàng)建解取,就是說你調(diào)用的view屬性的getter:[self view]步责。在getter里會先判斷view是否創(chuàng)建,如果沒有創(chuàng)建,那么會調(diào)用loadView來創(chuàng)建view蔓肯。loadView完成時會繼續(xù)調(diào)用viewDidLoad遂鹊。loadView和viewDidLoad的一個區(qū)別就是:loadView時還沒有view。而viewDidLoad時view以及創(chuàng)建好了蔗包。當view被添加其他view中之前時秉扑,會調(diào)用viewWillAppear,而之后會調(diào)用viewDidAppear调限。當view從其他view中移出之前時舟陆,會調(diào)用viewWillDisAppear,而之后會調(diào)用viewDidDisappear旧噪。當view不在使用吨娜,而且是disappeared脓匿,受到內(nèi)存警告時淘钟,那么viewController會將view釋放并將其指向nil。

三陪毡、代碼組織(如何設計良好的viewcontroller)

ViewController生命周期中有那么多函數(shù)米母,一個重要問題就是什么代碼該寫在什么地方。

  • 1毡琉、init里不要出現(xiàn)創(chuàng)建view的代碼。良好的設計,在init里應該只有相關數(shù)據(jù)的初始化推穷,而且這些數(shù)據(jù)都是比較關鍵的數(shù)據(jù)既绩。init里不要掉self.view,否則會導致viewcontroller創(chuàng)建view丐谋。(因為view是lazyinit的)芍碧。
  • 2、loadView中只初始化view号俐,一般用于創(chuàng)建比較關鍵的view如tableViewController的tabView泌豆,UINavigationController的navgationBar,不可掉用view的getter(在掉super loadView前)吏饿,最好也不要初始化一些非關鍵的view踪危。如果你是從nib文件中創(chuàng)建的viewController在這里一定要首先調(diào)用super的loadView方法,但建議不要重載這個方法猪落。
  • 3贞远、viewDidLoad 這時候view已經(jīng)有了,最適合創(chuàng)建一些附加的view和控件了笨忌。有一點需要注意的是蓝仲,viewDidLoad會調(diào)用多次(viewcontroller可能多次載入view,參見圖2)。
  • 4杂曲、viewWillAppear 這個一般在view被添加到superview之前庶艾,切換動畫之前調(diào)用。在這里可以進行一些顯示前的處理擎勘。比如鍵盤彈出咱揍,一些特殊的過程動畫(比如狀態(tài)條和navigationbar顏色)。
  • 5棚饵、viewDidAppear 一般用于顯示后煤裙,在切換動畫后,如果有需要的操作噪漾,可以在這里加入相關代碼硼砰。
  • 6、viewDidUnload iOS6中欣硼,viewDidUnload回調(diào)方法被Deprecated掉了

出現(xiàn)的問題

1题翰、 (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 可以查找XIB中有沒有視圖view。如果有诈胜,則不會再走loadView豹障。如果這個時候你的VC是沒有xib的,哪么顯然走這個方法后焦匈,是找不到任何view的血公,即self.view 仍為nil.然后,就跑loadview,這個時候會被觸發(fā)缓熟,如果在loadView中累魔,什么也不做,也不實例化一個View够滑。哪么程序繼續(xù)跑到viewDidLoad里垦写,如果這里還是沒有實例化VIEW。哪么這個VC就沒有視窗版述。在這里很多時侯會出現(xiàn)一個誤區(qū)(死循環(huán))梯澜。

  • 死循環(huán)的原因
    1、沒有XIB渴析。
    2晚伙、ViewController中的loadView方法中沒有做任何實例化self.view的操作。如:
    -(void)loadView
    {
    寫了一大堆代碼俭茧,但最好并沒有執(zhí)行以下兩種方式中的其中一種咆疗。
    //方式一:實例化時使用[supper loadView];
    //方式二 : self.view = [UIView alloc]....
    }
    3、在viewDidLoad中調(diào)用了self.view母债。
    只要這三個條件同時滿足午磁,必定死循環(huán)尝抖。方式一時,調(diào)用了[Supper LoadView] 這個時候由父類產(chǎn)生了一個(0,20,Width,height )迅皇。這里的寬高根據(jù)是IPAD昧辽,還是IPHONE不同而不同,但原點坐標一定是(0,20)即去除狀態(tài)條登颓。方式二搅荞,沒有對self.view作任可賦值,所以使得self.View = nil;
    在條件二滿足的情況下框咙,程序運行到步驟三咕痛,這個時候,如果在這里調(diào)用了self.View喇嘱。因為self.View在步驟二中為空茉贡,所以又回調(diào)到了loadView來,但因loadView中沒有對self.View作實例化者铜,于是在跑完loadView后腔丧,又繼續(xù)跑viewDidLoad,但因ViewDidLoad中又沒有實例化的情況下王暗,使用了self.View.因此就出會現(xiàn)來回調(diào)用的現(xiàn)象悔据。

2庄敛、initWithCoder不調(diào)用
initWithCoder 是一個類在IB中創(chuàng)建但在xocde中被實例化時被調(diào)用的.比如,通過IB創(chuàng)建一個controller的nib文件,然后在xcode中通過 initWithNibName來實例化這個controller,那么這個controller的initWithCoder會被調(diào)用.或者是一個view的nib文件俗壹,類似方法創(chuàng)建時調(diào)用initWithCoder

UIView的機制

  1. initWithFrame方法是什么?
    initWithFrame方法用來初始化并返回一個新的視圖對象,根據(jù)指定的CGRect(尺寸)藻烤。
    當然绷雏,其他UI對象,也有initWithFrame方法怖亭,但是涎显,我們以UIView為例,來搞清楚initWithFrame方法兴猩。

  2. 什么時候用initWithFrame方法期吓?
    簡單的說,我們用編程方式申明倾芝,創(chuàng)建UIView對象時讨勤,使用initWithFrame方法。
    在此晨另,我們必須搞清楚潭千,兩種方式來進行初始化UIView。
    1.使用 Interface Builder 方式借尿。
    這種方式刨晴,就是使用nib文件屉来。通常我們說的“拖控件” 的方式。

實際編程中狈癞,我們?nèi)绻肐nterface Builder 方式創(chuàng)建了UIView對象茄靠。(也就是,用拖控件的方式)
那么蝶桶,initWithFrame方法方法是不會被調(diào)用的嘹黔。因為nib文件已經(jīng)知道如何初始化該View。(因為莫瞬,我們在拖該view的時候儡蔓,就定義好了長、寬疼邀、背景等屬性)喂江。
這時候,會調(diào)用initWithCoder方法旁振,我們可以用initWithCoder方法來重新定義我們在nib中已經(jīng)設置的各項屬性获询。

這就是為什么使用initWithCoder:的原因,因為BIDViewController.xib的view是BIDQuartzFunView類型拐袜,而不是UIView類型了吉嚣,所以其實是從nib中加載對象實例。

  • 使用編程方式蹬铺。
    就是我們聲明一個UIView的子類尝哆,進行“手工”編寫代碼的方式。

實際編程中甜攀,我們使用編程方式下秋泄,來創(chuàng)建一個UIView或者創(chuàng)建UIView的子類。這時候规阀,將調(diào)用initWithFrame方法恒序,來實例化UIView。
特別注意谁撼,如果在子類中重載initWithFrame方法歧胁,必須先調(diào)用父類的initWithFrame方法。在對自定義的UIView子類進行初始化操作厉碟。
比如:

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];// 先調(diào)用父類的initWithFrame方法
    if (self) {
        
        // 再自定義該類(UIView子類)的初始化操作喊巍。
        _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
        [_scrollView setFrame:CGRectMake(0, 0, 320, 480)];
        _scrollView.contentSize = CGSizeMake(320*3, 480);
        
        [self addSubview:_scrollView];
    }
    return self;
}

在這里,我想墨榄,應該對initWithFrame方法略知一二了玄糟。

當我們所寫的程序里沒用用Nib文件(XIB)時,用代碼控制視圖內(nèi)容,需要調(diào)用initWithFrame去初始化

- (id)initWithFrame:(CGRect)frame
{
    if (self =[superinitWithFrame:frame]) {
        // 初始化代碼
    }
    return self;
}

用于視圖加載nib文件袄秩,從nib中加載對象實例時阵翎,使用 initWithCoder初始化這些實例對象

- (id)initWithCoder:(NSCoder*)coder
{
    if (self =[superinitWithcoder:coder]) {
        // 初始化代碼
    }
    return self;
}

1.initWithCoder: 對于.xib逢并,當你嵌入一個視圖對象到xib,視圖加載時默認調(diào)用的是該方法郭卫;例如:假如創(chuàng)建的view來自nib砍聊,那么將會調(diào)用initWithCoder,由系統(tǒng)來調(diào)用贰军,自己不能調(diào)用玻蝌。
2.initWithFrame: 非.xib的手動編碼,視圖加載時默認調(diào)用的是該方法词疼。是由自己調(diào)用俯树,來初始化對象的

問題:

1、初始化view時不管用什么方式贰盗,

//添加lifeview许饿,檢測view生命周期
    self.lifeView = [[LifeView alloc] initWithFrame:CGRectMake(10, 500, 200, 20)];
    self.lifeView = [[LifeView alloc] init];
    [self.view addSubview:self.lifeView];

都會先調(diào)用

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor yellowColor];
    }
    return self;
}

init只有view用init初始化時才會調(diào)用

- (instancetype)init {
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor redColor];
    }
    return self;
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市舵盈,隨后出現(xiàn)的幾起案子陋率,更是在濱河造成了極大的恐慌,老刑警劉巖秽晚,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓦糟,死亡現(xiàn)場離奇詭異,居然都是意外死亡赴蝇,警方通過查閱死者的電腦和手機菩浙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扯再,“玉大人芍耘,你說我怎么就攤上這事∠ㄗ瑁” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵倔约,是天一觀的道長秃殉。 經(jīng)常有香客問我,道長浸剩,這世上最難降的妖魔是什么钾军? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮绢要,結果婚禮上吏恭,老公的妹妹穿的比我還像新娘。我一直安慰自己重罪,他們只是感情好樱哼,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布哀九。 她就那樣靜靜地躺著,像睡著了一般搅幅。 火紅的嫁衣襯著肌膚如雪阅束。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天茄唐,我揣著相機與錄音息裸,去河邊找鬼。 笑死沪编,一個胖子當著我的面吹牛呼盆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚁廓,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宿亡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纳令?” 一聲冷哼從身側響起挽荠,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎平绩,沒想到半個月后圈匆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡捏雌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年跃赚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片性湿。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡纬傲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肤频,到底是詐尸還是另有隱情叹括,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布宵荒,位于F島的核電站汁雷,受9級特大地震影響,放射性物質發(fā)生泄漏报咳。R本人自食惡果不足惜侠讯,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望暑刃。 院中可真熱鬧厢漩,春花似錦、人聲如沸岩臣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粱胜,卻和暖如春柄驻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背焙压。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工鸿脓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涯曲。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓野哭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親幻件。 傳聞我的和親對象是個殘疾皇子拨黔,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容