2012-05-24 30 views
3

使用上的Xcode 4.3.2空應用程序模板,創建一個項目,所以沒有參與NIB。誰調整了我的觀點? (iOS上)

FooViewController.m

-(void) loadView { 
    UIView *view = [[UIView alloc] init]; 
    view.backgroundColor = [UIColor yellowColor]; 
    self.view = view;      
} 

因此,一個視圖被實例化並分配給self.view。兩種方法:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    NSLog(@"self.view is %@", self.view); 
} 

-(void) viewDidAppear:(BOOL)animated { 
    NSLog(@"self.view is %@", self.view); 
} 

而第二個打印出

self.view is <UIView: 0x18e4d0; frame = (0 20; 768 1004); layer = <CALayer: 0x182a00>> 

所以viewDidLoadviewDidAppear之間,該視圖被調整大小的第一種方法將打印出

self.view is <UIView: 0x18e4d0; frame = (0 0; 0 0); layer = <CALayer: 0x182a00>> 

。調整它的機制是什麼?我們可以指望它嗎?因爲即使馬特紐伯格,高度重視的書籍編程iOS,第二版的作者,這樣做(如第508頁)。

回答

0

默認情況下,autoresizesSubviews屬性將導致一個視圖顯示時,以調整其子視圖。

+0

如果我添加了'[[UIApplication的sharedApplication] keyWindow] .autoresizesSubviews = NO;'到viewDidLoad'的'年底,觀點依然是調整 –

0

self.view不實際創建,直到它顯示在屏幕上。這是懶加載。在調用viewWillAppear之後,幀將被設置。是的,您可以信任這些值,因爲它們是根據手機的屏幕和方向進行設置的。

self.view是一個比較特殊的看法,我往往不直接與它的工作,我通常只是添加一個容器子視圖,並將其視爲主視圖。由於調整大小,最好不要將self.view視爲靜態實體。確保適當設置子視圖的自動調整掩碼,以便在self.view更改時正確顯示它們。

爲了進一步回答你的問題,UIKit專門設置了視圖的框架,以考慮屏幕的大小,方向,導航欄,狀態欄,工具欄等。不保證你在viewWillAppear之前設置的框架被稱爲,將是相同的。事實上,如果導航欄,方向或其他因素髮生變化,self.view會更改。因此,即使在viewWillDisplay之後,您也無法保證self.view的靜態尺寸,如果您更改了它,它將被正確重置以反映設備的狀態。

UIKit爲我們照顧這個實現細節,這是一種奢望,因爲那樣我們就不必考慮設備特定的更改,只要確保適當地設置子視圖的自動調整大小,並且UIKit負責其餘部分。

+0

這兩個的NSLog行打印出完全一樣的東西...... –

3

你必須瞭解的ViewController的生命週期。 在viewDidLoad中,將創建視圖,但不會設置邊界/尺寸。這將在下一步中發生。您可以使用viewWillAppear來設置維度(大多數人都這麼做)。 ViewDidAppear發生在最後,在那裏你已經有了最後的外觀和動畫已經開始。

所以是的,viewDidLoad中和viewDidAppear之間,視圖得到它的尺寸和邊界,這是完全可靠的,並記錄在視圖控制器文檔。

還要注意,每次需要創建視圖時都會調用viewDidLoad(如第一次和低內存警告後 - 當需要內存時通常會釋放視圖 - ),並且viewWillAppear將在每次視圖控制器時被調用位於堆棧頂部,其視圖即將呈現。

看一看關於視圖外觀的文檔: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDisplay-Notifications/RespondingtoDisplay-Notifications.html#//apple_ref/doc/uid/TP40007457-CH12

+1

似乎正確的...但是,如果一個空的方法'viewWillAppear'被定義爲覆蓋默認行爲,該視圖仍然調整大小... –

+0

100多頁的ViewController編程指南...你不能說iOS沒有很好地記錄... –

+0

這就是爲什麼我建議使用容器視圖。直接使用self.view是一種痛苦,就像x一樣,y尺寸將始終保持不變,即使顯示翻轉時也是如此。這是一個特殊的觀點,因爲操作系統直接對該視圖進行更改。如果你使用'bounds'而不是'frame',你應該沒有這個問題 –

0

看起來viewControllerview被調整當你做出這個viewController一個rootViewControllerapplication的的window。否則,你必須手動設置它的框架。

我試過這段代碼:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.window.backgroundColor = [UIColor whiteColor]; 

    FooViewController *viewController = [[FooViewController alloc] init]; 

    self.window.rootViewController = viewController; 
    [self.window makeKeyAndVisible]; 

    FooViewController *viewController2 = [[FooViewController alloc] init]; 
    [viewController.view addSubview: [viewController2 view]]; 

    return YES; 
} 

viewController進行調整和viewController2不是。

也包括:viewController被稱爲這一切的方法:

viewDidLoad 
viewWillLayoutSubviews 
viewDidLayoutSubviews 
viewDidAppear 

viewController2viewDidLoadviewDidAppear被稱爲。

同樣有趣的是:viewController在調用viewWillLayoutSubviews之前被調整大小。

編輯:

我想這是值得進一步測試。使用下面的代碼:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.window.backgroundColor = [UIColor whiteColor]; 

    FooViewController *viewController = [[FooViewController alloc] init]; 
    NSLog(@"after init: self.view is %@", viewController.view); 
    self.window.rootViewController = viewController; 
    NSLog(@"after setting to rootViewController: self.view is %@", viewController.view); 
    [self.window makeKeyAndVisible]; 
    NSLog(@"after makeKeyAndVisible: self.view is %@", viewController.view); 

    return YES; 
} 

結果:

viewDidLoad:       frame = (0 0; 0 0) 
after init:       frame = (0 0; 0 0) 
after setting to rootViewController: frame = (0 0; 0 0) 
after makeKeyAndVisible:    frame = (0 20; 320 460) 
viewWillLayoutSubviews:    frame = (0 20; 320 460) 
viewDidLayoutSubviews:    frame = (0 20; 320 460) 
viewDidAppear:      frame = (0 20; 320 460) 

所以[self.window makeKeyAndVisible];是罪魁禍首。