一:主窗口根控制器切换。有时候,在程序里面用到切换底层主窗口的根控制器的时候,我们需要找出这个主窗口。切换主窗口根控制器有以下几个方法1,2,3,4,5:
GuidePageController *log=[[GuidePageController alloc]init];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:log];
UIWindow * window = [UIApplication sharedApplication].delegate.window;//1
//UIWindow * window = [UIApplication sharedApplication].windows[0];//2
window.rootViewController=nav;
//self.view.window.rootViewController=nav;//3
//[UIApplication sharedApplication].keyWindow.rootViewController=nav;//4
//presentViewController切换//5
二:MBProgressHUD使用注意点,很多时候我们都不用MBProgressHUD的原始方法去给用户提示一些信息,而是去用大神们去封装好的一些分类方法,这样节省了很多代码量。像MBProgressHUD+MJ等等。但是以下情况使用的时候我们要注意一下。我们以MBProgressHUD+MJ为例子做一个分析。
例子:比如我们要做一个登陆界面:
[MBProgressHUD showMessage:@"正在登录中...."];
AFHTTPRequestOperationManager*mager=[AFHTTPRequestOperationManager manager];
[mager POST:url parameters:nil success:^(AFHTTPRequestOperation * operation, id responseObject) {
[MBProgressHUD hideHUD];
[UIApplication sharedApplication].keyWindow.rootViewController=新的根控制器;
} failure:^(AFHTTPRequestOperation * operation, NSError * error) {
[MBProgressHUD hideHUD];
}];
以上代码没问题,但是如果我们需要一个登陆成功提醒的话,那么代码可能会这样:
[MBProgressHUD showMessage:@"正在登录中...."];
AFHTTPRequestOperationManager*mager=[AFHTTPRequestOperationManager manager];
[mager POST:url parameters:nil success:^(AFHTTPRequestOperation * operation, id responseObject) {
[MBProgressHUD hideHUD];
[MBProgressHUD showSuccess:@"登录成功"];
[UIApplication sharedApplication].keyWindow.rootViewController=新的根控制器;
} failure:^(AFHTTPRequestOperation * operation, NSError * error) {
[MBProgressHUD hideHUD];
}];
这时候页面可能会出现Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior ()这个错误。我们追随[MBProgressHUD showSuccess:]进入看一下发现最终会走到这个方法里面:
+ (void)show:(NSString *)text icon:(NSString *)icon view:(UIView *)view
{
if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
// 快速显示一个提示信息
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
hud.labelText = text;
// 设置图片
hud.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"MBProgressHUD.bundle/%@", icon]]];
// 再设置模式
hud.mode = MBProgressHUDModeCustomView;
// 隐藏时候从父控件中移除
hud.removeFromSuperViewOnHide = YES;
// 1秒之后再消失
[hud hide:YES afterDelay:1.0];
}
这里面我们来看这四行代码:
if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
// 快速显示一个提示信息
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
// 隐藏时候从父控件中移除
hud.removeFromSuperViewOnHide = YES;
// 1秒之后再消失
[hud hide:YES afterDelay:1.0];
一下纯属我个人理解:如果有不对的地方,还请多多指教。
什么意思呢?就是这个hud显示在主窗口的最后一个view上面了,隐藏时就从这个view上面移除。而这个hud会在1秒之后隐藏。接着,在这1秒内我们的程序已经走到了[UIApplication sharedApplication].keyWindow.rootViewController=新的根控制器;这一步,也就是切换了新的根控制器,没有指针在指向那个根控制器,那么之前所有根控制器里面的控制器以及他们的view都会被系统回收销毁。1秒后呢,hud开始隐藏,这时候hud的父控件早已经被销毁了,找不到父控件。就会报出以上的错误了。所以我们要要在隐藏之后再切换根控制器。
代码改进:我们显示登录成功的那个提示要单独做,首先在.m文件添加一个属性,@property (strong, nonatomic) MBProgressHUD *hud;
[MBProgressHUD showMessage:@"正在登录中...."];
AFHTTPRequestOperationManager*mager=[AFHTTPRequestOperationManager manager];
[mager POST:url parameters:nil success:^(AFHTTPRequestOperation * operation, id responseObject) {
[MBProgressHUD hideHUD];
_hud = [MBProgressHUD showHUDAddedTo:[[UIApplication sharedApplication].windows lastObject] animated:YES];
_hud.labelText = @"登录成功";
// 设置图片
_hud.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"MBProgressHUD.bundle/%@", @"success.png"]]];
// 设置模式
_hud.mode = MBProgressHUDModeCustomView;
//是否有庶罩
_hud.dimBackground = YES;
// 隐藏时候从父控件中移除
_hud.removeFromSuperViewOnHide = YES;
// 1秒之后执行一下方法
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 立即隐藏
[_hud hide:YES];
[UIApplication sharedApplication].keyWindow.rootViewController=新的根控制器;
});
} failure:^(AFHTTPRequestOperation * operation, NSError * error) {
[MBProgressHUD hideHUD];
}];