天天看點

iOS,視圖控制器相關(UIViewController)

1.視圖控制器各個方法調用時機

2.頁籤(Tab Bar)和導航欄(Navigation Bar)

3.有無控制器的頁面跳轉

4.頁面跳轉隐藏底部頁籤

5.擷取導航欄和狀态欄高度,隐藏導航欄傳回按鈕、導航控制器,隐藏狀态欄

6.模态視圖的彈出動畫和彈出風格

7.移除main.storyboard,解決總是進入ViewController

9.視圖控制器不進入dealloc的幾種原因 

10.app鎖屏相關

11.設定導航控制器字型顔色等

12.獲得目前螢幕顯示的ViewController

視圖控制器各個方法調用時機

init:方法

在init方法中執行個體化必要的對象(遵從LazyLoad思想) init方法中初始化ViewController本身   loadView:方法 這是當沒有正在使用nib視圖頁面,子類将會建立自己的自定義視圖層。絕不能直接調用   viewDidLoad:方法 在視圖加載後被調用   viewWillAppear:方法 視圖即将可見時調用   viewDidAppear:方法 視訊完全過渡到螢幕上時調用   viewWillDisappear:方法 視圖被駁回時調用,覆寫或以其他方式隐藏   viewDidDisappear:方法 視圖被駁回後調用,覆寫或以其他方式隐藏   當A視圖切換到B視圖時,順序流程 1.B視圖的viewDidLoad 2.A視圖的viewWillDisappear 3.B視圖的viewWillAppear 4.A視圖viewDidDisappear 5.B視圖viewDidAppear     viewWillLayoutSubviews:方法 控制器的view将要布局子控件   viewDidLayoutSubviews:方法 控制器的view布局子控件完成   任何原因引起View的尺寸被改變;這期間系統可能會多次調用viewWillLayoutSubviews、viewDidLayoutSubviews 倆個方法  

didReceiveMemoryWarning:方法

記憶體不足情況下視圖控制器會收到這條消息;并不代表該應用占用了很多記憶體,也有可能是背景有很多程式占用了記憶體;收到警告後可以嘗試釋放記憶體(記憶體大戶圖像、視訊、聲音等)不是立刻需要的東西。(如果iOS認為你占用了很多記憶體是可以殺掉app的,比如在堆中存放20個視訊等不合理使用記憶體的操作)

頁籤(Tab Bar)和導航欄(Navigation Bar)

//AppDelegate.h檔案

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property(strong,nonatomic) UITabBarController *tabBarController;//底部頁籤控制器

@end      

//AppDelegate.m檔案

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

    //消息控制器
    MessageViewController *msgController=[[MessageViewController alloc] init];
    UINavigationController *navMsg=[[UINavigationController alloc] initWithRootViewController:msgController];
    //頁籤的圖檔樣式以這種方式處理,避免圖檔無法完全顯示
    UITabBarItem *msgTabItem = [[UITabBarItem alloc]initWithTitle:@"消息" image:[[UIImage imageNamed:@"[email protected]"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"[email protected]"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
    navMsg.tabBarItem=msgTabItem;

    

    //聯系人控制器
    ContactViewController *conController=[[ContactViewController alloc] init];
    UINavigationController *navCon=[[UINavigationController alloc] initWithRootViewController:conController];
    UITabBarItem *conTabItem = [[UITabBarItem alloc]initWithTitle:@"聯系人" image:[[UIImage imageNamed:@"tab_ [email protected]"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"tab_ [email protected]"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
    navCon.tabBarItem=conTabItem;
    

    //動态控制器
    DynamicViewController *dynController=[[DynamicViewController alloc] init];
    UINavigationController *navDyn=[[UINavigationController alloc] initWithRootViewController:dynController];
    UITabBarItem *dynTabItem = [[UITabBarItem alloc]initWithTitle:@"動态" image:[[UIImage imageNamed:@"tab_ [email protected]"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"tab_ [email protected]"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
    navDyn.tabBarItem=dynTabItem;

    self.tabBarController=[[UITabBarController alloc] init];
    self.tabBarController.viewControllers=@[navMsg,navCon,navDyn];
    self.tabBarController.selectedIndex=0;

    //由于iPhone是單視窗程式,是以也就隻有這麼一個Window對象,而且是UIWindow,不是NSWindow。而根據文檔上所說:這個是便捷方法,去使被使用對象的主視窗顯示到螢幕的最前端。
    [self.window makeKeyAndVisible];
    return YES; 
}      

//底部頁籤顯示未讀消息

self.navigationController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%ld",(long)count];      

 //應用圖示消失未讀消息

[UIApplication sharedApplication].applicationIconBadgeNumber = count;      

有無控制器的頁面跳轉

pushviewController是UINavigationController推到一個新viewController

//以棧的方式管理視圖,各個視圖的切換就是壓棧和出棧操作,出棧後的視圖會立即銷毀。

[self.navigationController pushViewController:qqContactController animated:YES];//将視圖壓入棧内,後顯示      

//直接跳轉到根控制器

[self.navigationController popToRootViewControllerAnimated:YES];      

//傳回到上一層控制器(可以改變索引指定傳回到前幾個控制器)

[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:([self.navigationController.viewControllers count]-2)] animated:YES];      

  //從棧中彈出該視圖控制器(傳回到上一層控制器)

[self.navigationController popViewControllerAnimated:YES];      

  presentViewController彈出模态視圖(模态視圖顯示的時候不能對其他視圖進行操作,例如UIAlertView)

//彈出模态視圖

[self presentViewController:view animated:YES completion:nil];//彈出視圖,不過是全屏不帶navigation bar的。      

//隐藏銷毀模态視圖

[self dismissViewControllerAnimated:YES completion:nil];      

頁面跳轉隐藏底部頁籤

//在push到其他控制器要隐藏底部頁籤時,在需要跳轉的控制器初始化方法下處理hidesBottomBarWhenPushed

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // 将hidesBottomBarWhenPushed屬性設定如果為YES,當這個控制器push的時候,底部的Bar,比如Tabbar會滑走,也就是不會在push後的視圖上顯示出來,預設值為NO。
            //這個屬性隻支援非自定義的Tabbar,也就是隻支援原生Tabbar,
            self.hidesBottomBarWhenPushed = YES;
        }
     return self;
}      

//或者在跳轉前設定

[ctr setHidesBottomBarWhenPushed:YES];      

擷取導航欄和狀态欄高度,隐藏導航欄傳回按鈕、導航控制器,隐藏狀态欄

CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame]; // 狀态欄(statusbar)

float statusHeight=rectStatus.size.height; //狀态欄高度

float navHeight=self.navigationController.navigationBar.frame.size.height; //導航欄高度      

 //隐藏導航控制器傳回按鈕

[self.navigationItem setHidesBackButton:YES];       

 //隐藏導航控制器

[self.navigationController setNavigationBarHidden:YES animated:NO];      

//隐藏狀态欄

- (BOOL)prefersStatusBarHidden
{
    return YES;//隐藏為YES,顯示為NO
}      

模态視圖的彈出動畫和彈出風格

//彈出動畫

typedef enum {
        UIModalTransitionStyleCoverVertical = 0,//視圖從螢幕底部幻燈片,預設
        UIModalTransitionStyleFlipHorizontal,//目前視圖啟動水準3 d從從右到左的翻轉,導緻新視圖的暴露,就好像它是在前面的視圖
        UIModalTransitionStyleCrossDissolve,//視圖淡出
        UIModalTransitionStylePartialCurl,//從目前視圖右下角卷起
} UIModalTransitionStyle;      

//彈出風格

typedef enum {
    UIModalPresentationFullScreen = 0,//彈出VC充滿全屏
    UIModalPresentationPageSheet,//VC高度和目前螢幕高度相同,寬度和豎屏模式下螢幕寬度相同,剩餘未覆寫區域将會變暗并阻止使用者點選,這種彈出模式下,豎屏時跟UIModalPresentationFullScreen的效果一樣,橫屏時候兩邊則會留下變暗的區域。
    UIModalPresentationFormSheet,//VC的高度和寬度均會小于螢幕尺寸,VC居中顯示,四周留下變暗區域。
    UIModalPresentationCurrentContext,//VC的彈出方式和該VC的父VC的方式相同。
} UIModalPresentationStyle;      
這四種方式在iPad上面統統有效,但在iPhone和iPod touch上面系統始終已UIModalPresentationFullScreen模式顯示presented VC。

//例:      
TestViewController *view=[[TestViewController alloc] init];
//彈出動畫
//    view.modalTransitionStyle=UIModalTransitionStyleCoverVertical;//視圖從螢幕底部幻燈片,預設
    view.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;//視圖淡出
//    view.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;//目前視圖啟動水準3 d從從右到左的翻轉,導緻新視圖的暴露,就好像它是在前面的視圖
//    view.modalTransitionStyle=UIModalTransitionStylePartialCurl;//從目前視圖右下角卷起
    [self presentViewController:view animated:YES completion:nil];      

移除main.storyboard,解決總是進入ViewController

在info.plist中删除下面一行

iOS,視圖控制器相關(UIViewController)

在工程中General中去掉關聯

iOS,視圖控制器相關(UIViewController)

注意APPDelegate裡面要加

[self.window makeKeyAndVisible];

視圖控制器不進入dealloc的幾種原因 

  dealloc方法之是以沒有被調用時因為控制器的一個或多個強引用仍然在記憶體中,也就是目前控制器的計數器不為0 一般的幾種原因:

  • 1.定時器沒有被銷毀, 解決方法:在viewWillDisappear需要把控制器用到的NSTimer銷毀
    //調用一次定時器 
    NSTimer  *myTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:selfselector:@selector(hideView) userInfo:nil repeats:NO];
    //多次調用定時器,将reperats設定為YES
     NSTimer  *myTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:selfselector:@selector(hideView) userInfo:nil repeats:YES];
    
    //取消定時器,永久停止,需要将timer設定為nil
    [myTimer invalidate];
        myTimer = nil;
    
    //關閉定時器
    [myTimer setFireDate:[NSDate distantFuture]];
    
    //開啟定時器
    [myTimer setFireDate:[NSDate distantPast]];      
  • 2.block塊使用不當,因為block會對方法中的變量自動retain移除,請檢查控制器中的block代碼
  • 3.代理必須得用weak修飾,用strong強引用會導緻計數器加1,無法釋放記憶體。
  • 4.在getter方法裡使用self,導緻死循環

app鎖屏相關

// 禁止自動鎖屏
[UIApplication sharedApplication].idleTimerDisabled = YES;

// 允許自動鎖屏
[UIApplication sharedApplication].idleTimerDisabled = NO;      

設定導航控制器字型顔色等

//設定标題
self.title=@"牛牛設定";
//設定标題顔色字型大小
[self.navigationController.navigationBarsetTitleTextAttributes:@{NSFontAttributeName:[UIFontsystemFontOfSize:19],NSForegroundColorAttributeName:[UIColorcolorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1]}];
//修改導航欄背景色
[self.navigationController.navigationBar setBarTintColor:[UIColorcolorWithRed:30/255.0 green:144/255.0 blue:255/255.0 alpha:0.5]];
//更改傳回按鈕顔色
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
//下一個視圖的傳回按鈕檔案會改變為下面設定的值
UIBarButtonItem *returnButtonItem = [[UIBarButtonItem alloc] init];
returnButtonItem.title = @"";
self.navigationItem.backBarButtonItem = returnButtonItem;        

獲得目前螢幕顯示的ViewController

/**
 獲得目前螢幕顯示的ViewController
 适用範圍tabbar的子視圖都是NavigationController,
 或有NavigationController的視圖控制器
 @return 傳回目前正在顯示的視圖控制器
 */
- (UIViewController *)getCurrentVC{
    UIViewController *result = nil;
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    //app預設windowLevel是UIWindowLevelNormal(預設的水準。使用這個級别的大部分内容,包括為您的應用程式的主視窗。),如果不是,找到UIWindowLevelNormal的
    if (window.windowLevel != UIWindowLevelNormal)
    {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for(UIWindow * tmpWin in windows)
        {
            if (tmpWin.windowLevel == UIWindowLevelNormal)
            {
                window = tmpWin;
                break;
            }
        }
    }
    id  nextResponder = nil;
    UIViewController *appRootVC=window.rootViewController;
    //    如果是present上來的appRootVC.presentedViewController 不為nil
    if (appRootVC.presentedViewController) {
        nextResponder = appRootVC.presentedViewController;
    }else if(appRootVC.childViewControllers){
        //如果有子視圖控制器
        while (appRootVC.childViewControllers>0) {
            if ([appRootVC isKindOfClass:[UINavigationController class]]) {
                appRootVC=[appRootVC.childViewControllers lastObject];
                break;
            }
            else if ([appRootVC isKindOfClass:[UITabBarController class]]){
                UITabBarController * tabbar = (UITabBarController *)appRootVC;
                appRootVC=(UINavigationController *)tabbar.viewControllers[tabbar.selectedIndex];
            }
            else{
                for (int i=0; i<appRootVC.childViewControllers.count; i++) {
                    //isViewLoaded 表示已經視圖被加載過 view.window表示視圖正在顯示
                    if ([appRootVC.childViewControllers objectAtIndex:i].isViewLoaded && [appRootVC.childViewControllers objectAtIndex:i].view.window) {
                        appRootVC=[appRootVC.childViewControllers objectAtIndex:i];
                        break;
                    }
                }
            }
        }
        nextResponder=appRootVC;
    }else{
        UIView *frontView = [[window subviews] objectAtIndex:0];
        //nextResponder傳回接收器的下一個應答器(見UIResponder+Router進行事件分發)
        nextResponder = [frontView nextResponder];
    }
    result = nextResponder;
    return result;
}      

轉載于:https://www.cnblogs.com/douniwanxia/p/5887585.html

繼續閱讀