2.选项卡(Tab Bar)和导航栏(Navigation Bar)
5.获取导航栏和状态栏高度,隐藏导航栏返回按钮、导航控制器,隐藏状态栏
7.移除main.storyboard,解决总是进入ViewController
init:方法
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:@"tab_message@3x.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"tab_message_select@3x.png"] 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_ contact@3x.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"tab_ contact_select@3x.png"] 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_ dynamic@3x.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"tab_ dynamic_select@3x.png"] 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];
//弹出模态视图
[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中删除下面一行
在工程中General中去掉关联
注意APPDelegate里面要加
[self.window makeKeyAndVisible];
-
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,导致死循环
// 禁止自动锁屏 [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 适用范围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; }