O~1iOS开发(OC)

iOS日常问题总结

2017-03-15  本文已影响238人  最后还是个农

在外包公司成长中,遇到各种各样项目,总结一些遇到的问题。
日常工作中用到的一些方法总结,有很简单介绍,可能也有错误,如果您看到了希望可以告诉我,会不间断更新。

一、iOS 10以后拨打电话

iOS 10以后,原来拨打电话的几种方式都不太好用,反应特别慢,苹果更新的新的API,使用openURL:options:completionHandler:替代了openURL,具体讲解请点击,谢谢大神的分享。

示例代码:
if (@available(iOS 10.0, *)) {
        // 拨打电话 iOS 10以后
        NSMutableString *str=[[NSMutableString alloc] initWithFormat:@"tel://%@",@"132****0983"];
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str] options:@{} completionHandler:nil];
    } else {
        // 拨打电话 iOS 10以前
        NSMutableString *str=[[NSMutableString alloc] initWithFormat:@"tel://%@",@"132****0983"];
        UIWebView *callWebview = [[UIWebView alloc] init];
        [callWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:str]]];
        [self.view addSubview:callWebview];
    }

二、UIWebVIew加载网页时,让网页适应屏幕大小

self.webView.scalesPageToFit = YES;

三、更改UILabel中字距边框的距离

要更改 Label 距离边框的距离就需要自定义 Label,需要重写drawTextInRect方法,重新绘制文本的位置;
代码示例:

-(void)drawTextInRect:(CGRect)rect{
    // 上下左右各距5
    [super drawTextInRect:CGRectMake(rect.origin.x + 5, rect.origin.y + 5, rect.size.width - 10, rect.size.height -10)];
}

三、解决“当子视图超出父视图范围,子视图点击事件无反应”问题

需要重写父视图的-hitTest:withEvent:

// self.backButton在父视图frame以外
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *view = [super hitTest:point withEvent:event];
    if (view == nil) {
        // 转换坐标系
        CGPoint newPoint = [self.backButton convertPoint:point fromView:self];
        // 判断触摸点是否在button上
        if (CGRectContainsPoint(self.backButton.bounds, newPoint)) {
            view = self.backButton;
        }
    }
    return view;
}

四、获取某个View所在控制器

写代码时,经常去封装一些视图,有时候在视图中去处理一些事件,难免会用到view所在的控制器,可以通过这个方法获取view所在控制器。

// 获取当前控制器
- (UIViewController *)findViewController:(UIView *)sourceView
{
    id target = sourceView;
    while (target) {
        target = ((UIResponder *)target).nextResponder;
        if ([target isKindOfClass:[UIViewController class]]) {
            break;
        }
    }
    return target;
}

五、UILabel显示html标签(字体的颜色和大小)

今天被这个问题问懵逼了,所以查查资料,学习下,经测试很好用。感谢sunboygpz的分享。
可以使用富文本来实现, 代码如下:

UILabel *label  = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 300, 200)];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:[@"<font  style='font-size:20px;color:red'  >666666666666666</font> asdasd " dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
    label.attributedText = attributedString;
    [self.view addSubview:label];

六、解决UITextField设置为密文输入时,再次输入会清空原有内容问题

在UITextField的代理方法中操作,实测好用,代码如下:

// self.passwordTF为密码输入框
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == self.passwordTF) {
        /// 解决密文输入时,再次输入清空问题
        NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
        textField.text = updatedString;
        return NO;
    }
    return YES;
}

七、解决UIScrollView上添加UISlider时,滑动slider出现的问题

在UIScrollView横向排了3个UIView,其中一个UIView中有UISlider。在左右滑动slider的时候,如果快速滑动slider不会动,scrollview会左右滑动。
可以通过重写UIScrollView 的-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;方法解决这个问题,事例代码如下:

/// 解决scrollView上滑动UISlider问题
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    UIView *result = [super hitTest:point withEvent:event];
    if ([result isKindOfClass:[UISlider class]]) {
        self.scrollEnabled = NO;
    }else {
        self.scrollEnabled = YES;
    }
    return result;
}

八、对URL中的中文进行转码

事例代码
NSString *url1 = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

九、关于存储下载文件路径问题

最近项目中需要下载文件,保存到本地,然后把文件路径和一些信息存到数据库,再次读取的时候根据数据库中文件路径去获取文件,发现一个问题,就是iOS8以后苹果公司为了安全每次重启APP的时候,沙盒中唯一编码路径都会发生改变,所以如果直接存会出现获取不到文件的问题,解决办法很简单,就是存储地址的时候只存你放文件的地址(口拙,不知如何描述),不存沙盒地址,再次取地址的时候再重新吧沙盒地址拼接上。示例如下:

// 存地址 filePath为文件路径 :/Users/hao/Library/Developer/CoreSimulator/Devices/7314558F-CF6E-486F-B83D-E39B3189C1E8/data/Containers/Data/Application/BD297778-550D-4888-B301-1ACC70C59BAA/Library/Caches/ListenFile/我害怕.mp3
NSArray *pathArr = [filePath componentsSeparatedByString:@"/"];
// 取后两位保存
model.savePath = [NSString stringWithFormat:@"%@/%@",pathArr[pathArr.count-2],pathArr.lastObject];

// 取地址
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:"本地存储路径"];

十、定时器的创建、暂停、继续、终止

1、创建:简单的举一种,有很多种创建方式,可以自行百度。
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updatePlaybackProgress) userInfo:nil repeats:YES];
2、暂停
[self.progressUpdateTimer setFireDate:[NSDate distantFuture]];
3、继续
[self.progressUpdateTimer setFireDate:[NSDate date]];
4、终止:
[_progressUpdateTimer invalidate]; _progressUpdateTimer = nil;

十一、Xib布局后代码修改约束的值

具体请看Xib布局后代码修改约束的值

十二、修改UITableView头视图的高度

有些情况下需要更新头视图的内容,难免会改变高度,其实只要设置好头视图的frame,然后重新设置为头视图就可以,代码如下:

[self.tableView beginUpdates];// 动画效果
[self.tableView setTableHeaderView:self.headerView(头视图)];
[self.tableView endUpdates];// 动画// 动画
修改UITableView头视图的高度.gif

十三、iOS中获取各种文件的目录路径的方法

记录下 IOS中获取各种文件的目录路径的方法很不错。

十四、外包公司的感受

很累,貌似很充实,但是自己成长的太慢,每天都是重复的工作内容,简单无趣,再下去要废掉了,决定逃离。

十五、音乐的后台播放、控制、信息的展示和处理中断事件

1、打开后台设置
TARGETS —> Capabilities —> Background Modes —> 勾选 Audio,AirPlay。。。这项。如图:

后台设置.png
2、AppDelegate中代码
在方法-application:didFinishLaunchingWithOptions:中设置并激活音频会话类别,这样就可以在后台播放了。代码如下
@interface AppDelegate ()
/// 后台任务的UIBackgroundTaskIdentifier
@property(assign,nonatomic)UIBackgroundTaskIdentifier bgTaskId;
@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 设置并激活音频会话类别
    _bgTaskId=[AppDelegate backgroundPlayerID:_bgTaskId];
return YES;
}
/// 设置并激活音频会话类别
+(UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId
{
    //设置并激活音频会话类别
    NSError* error;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
    [[AVAudioSession sharedInstance] setActive:YES error:&error];
    //允许应用程序接收远程控制
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    //设置后台任务ID
    UIBackgroundTaskIdentifier newTaskId=UIBackgroundTaskInvalid;
    newTaskId=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
    if(newTaskId!=UIBackgroundTaskInvalid&&backTaskId!=UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication] endBackgroundTask:backTaskId];
    }
    return newTaskId;
}

3、接收到远程控制事件
在上一步中允许了应用程序接收远程控制[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];,接着实现-remoteControlReceivedWithEvent:方法。

#pragma mark - 接收到远程控制事件
-(void)remoteControlReceivedWithEvent:(UIEvent *)event {
    if(event.type==UIEventTypeRemoteControl){
       
        switch (event.subtype)
        {
            case UIEventSubtypeRemoteControlPause:
                /// 暂停 (自行处理)
                if ([VLCMusicManage defaultPlayer].currentPlaylistItem && [VLCMusicManage defaultPlayer].isPlaying) {
                    [[VLCMusicManage defaultPlayer] pause];
                }
                break;
            case UIEventSubtypeRemoteControlPlay:
                /// 播放 (自行处理)
                if ([VLCMusicManage defaultPlayer].currentPlaylistItem && ![VLCMusicManage defaultPlayer].isPlaying) {
                    [[VLCMusicManage defaultPlayer] pause];
                }
                break;
            case UIEventSubtypeRemoteControlNextTrack:
                /// 下一曲 (自行处理)
                if ([VLCMusicManage defaultPlayer].musicPlayList.count != 0) {
                    
                    [[VLCMusicManage defaultPlayer] playNextItem];
                }
                
                break;
            case UIEventSubtypeRemoteControlPreviousTrack:
                /// 上一曲 (自行处理)
                if ([VLCMusicManage defaultPlayer].musicPlayList.count != 0) {
                    
                    [[VLCMusicManage defaultPlayer] playPreviousItem];
                }
                break;
            case UIEventSubtypeRemoteControlTogglePlayPause:
                break;
            default:
                break;
        }
    }
}

4、锁屏时,歌曲信息的展示 借鉴源,写的很清楚
设置锁屏界面显示信息的原理是通过设置一个系统的字典,当音频开始播放时,系统会自动从这个字典中读取要显示的信息,如果需要动态显示,我们只需要不断更新这个字典即可。首先需要添加<MediaPlayer/MediaPlayer.h>这个头文件。

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    //设置歌曲题目
    [dict setObject:@"题目" forKey:MPMediaItemPropertyTitle];
    //设置歌手名
    [dict setObject:@"歌手" forKey:MPMediaItemPropertyArtist];
    //设置专辑名
    [dict setObject:@"专辑" forKey:MPMediaItemPropertyAlbumTitle];
    //设置显示的图片
    UIImage *newImage = [UIImage imageNamed:@"43.png"];
    [dict setObject:[[MPMediaItemArtwork alloc] initWithImage:newImage] forKey:MPMediaItemPropertyArtwork];
    //设置歌曲时长
    [dict setObject:[NSNumber numberWithDouble:300] forKey:MPMediaItemPropertyPlaybackDuration];
    //设置已经播放时长
    [dict setObject:[NSNumber numberWithDouble:150] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; 
    //更新字典
    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict];

5、处理中断事件
我是在APPDelegate中处理的,代码如下:

  // 处理中断事件的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterreption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
/// 实现方法
//处理中断事件
-(void)handleInterreption:(NSNotification *)sender
{
    NSDictionary *info = sender.userInfo;
    AVAudioSessionInterruptionType type = (AVAudioSessionInterruptionType)[info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
    if (type == AVAudioSessionInterruptionTypeBegan) {
        //中断开始  自行处理暂停或者播放
        [[VLCMusicManage defaultPlayer] pause];
    }else{
        AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
        if (options == AVAudioSessionInterruptionOptionShouldResume) {
            //中断恢复
            [[VLCMusicManage defaultPlayer] pause];
        }
    }
}

打完收工

十六、关于webView加载html时,图片的自适应问题(2017.9.27修改)

(旧,不懂web前端,看不太懂,但是今天用的时候发现在图片小于屏幕的时候,不起效果)
#pragma mark - 修改html代码字符串,适应webview  
- (NSString *)adaptWebViewForHtml:(NSString *) htmlStr  {  
        NSMutableString *headHtml = [[NSMutableString alloc] initWithCapacity:0];  
        [headHtml appendString : @"<html>" ];            
        [headHtml appendString : @"<head>" ];            
        [headHtml appendString : @"<meta charset=\"utf-8\">" ];          
        [headHtml appendString : @"<meta id=\"viewport\" name=\"viewport\" content=\"width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=false\" />" ];            
        [headHtml appendString : @"<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />" ];           
        [headHtml appendString : @"<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\" />" ];            
        [headHtml appendString : @"<meta name=\"black\" name=\"apple-mobile-web-app-status-bar-style\" />" ];  
        [headHtml appendString : @"<style>img{width:100%;}</style>" ];  
        [headHtml appendString : @"<style>table{width:100%;}</style>" ];  
        [headHtml appendString : @"<title>webview</title>" ];  
        NSString *bodyHtml;  
        bodyHtml = [NSString stringWithString:headHtml];  
        bodyHtml = [bodyHtml stringByAppendingString:htmlStr];  
        return bodyHtml;  
}  

最新的 写在这里方便查找

处理HTMLString的方法:
NSString *htmls = [NSString stringWithFormat:@"<header><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'></header> <html> \n" "<head> \n" "</style> \n" "</head> \n" "<body>" "<script type='text/javascript'>" "window.onload = function(){\n" "var $img = document.getElementsByTagName('img');\n" "for(var p in $img){\n" " $img[p].style.width = '100%%';\n" "$img[p].style.height ='auto'\n" "}\n" "}" "</script>%@" "</body>" "</html>",htmlStr];

 [self.webView loadHTMLString:htmlString baseURL:nil];
处理HTMLString的原理:
原理就是用一个for循环,拿到所有的图片,对每个图片都处理一次,让图片的宽为100%,就是按照屏幕宽度自适应;让图片的高atuo,自动适应。

十七、UINavigationBar透明渐变情况下,tableView分区区头停留在顶部。

动图不太好看,实际效果还可以。


gif5新文件.gif

十八、 获取cell或者cell中的控件在屏幕中的位置

借鉴下,原文地址
主要使用方法:

-(CGRect)convertRect:(CGRect)rect  toView:(UIView *)view;
-(CGRect)convertRect:(CGRect)rect  fromView:(UIView *)view;

这个两个方法的傻瓜式讲解
1、获取cell在屏幕中的位置

CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];//获取cell在tableView中的位置
CGRect rectInSuperview = [tableView convertRect:rectInTableView toView:[tableView superview]];

2、cell中的控件(比如按钮)在屏幕中的位置

UIWindow* window = [UIApplication sharedApplication].keyWindow;
CGRect rect1 = [sender convertRect:sender.frame fromView:self.contentView];//获取button在contentView的位置
CGRect rect2 = [sender convertRect:rect1 toView:window];

十九、 修改UINavigationController的子视图控制器数组viewControllers

在开发过程中会有这种情况:从vc1push到vc2,再从vc2push到vc3,在vc3中想要直接返回vc1有很多种处理方法,但是在有系统侧滑手势时,侧滑返回就不好处理,这样就可以通过这种方法来修改。

VC3 *vc3 = [VC3 new];
[self.navigationController pushViewController:vc animated:YES];
// 控制器跳转完成后,修改viewControllers,移除中间控制器
NSMutableArray * controllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[controllers removeObjectsInRange:NSMakeRange(1, 1)];
self.navigationController.viewControllers = controllers;

大概就是这样,可以根据实际情况来修改,自测很好用。

二十、NSDateFormatter转换时间各种格式总结

年份
1、yyyy 表示四位年份,例如2017;
2、yy 表示年份的后两位,例如”2017“会显示“17”;
月份
1、MM 表示两位月份,例如:”十二月“显示为”12“、“4月”显示为“04”;
2、M 在两位月份时,依旧为两位,但是对于一位的月份,则去除前面的0,只显示一位,例如:”十二月“显示为”12“、“4月”显示为“4”。同理,天、小时、分钟、秒一样。
天
1、dd 表示当前月份的哪一天;
2、DD 表示是今年的第*天。
上下午
1、a 表示上下午。
小时
1、hh 表示12小时制;
2、HH 表示24小时制。
分钟
1、mm 表示分钟。
秒
1、s 表示秒。
星期
1、EEEE 表示“星期几”;
2、EEE 表示“周几”。

二十一、使用NSUserdefaults存储数据容易出现Bug

翻看以前的总结记录发现的这问题,复制过来
NSUserDefaults 存储的对象全是不可变的,例如不能存储NSMutableArray,需要先转为不可变数组,否则会发生崩溃。

二十二、iPhone X适配之状态栏和导航栏高度

iPhone X的状态栏的长高了,这给我这个做外包的👨‍💻‍造成了致命的打击,前期写代码的时候,受培训的时候老师影响,死板的认为状态栏的高度就是20,一直是写死,现在前前后后写了十几个项目,基本都需要售后日常维护,这是一个惨痛教训,请大家引以为戒,下面留下获取状态栏高度的方法。

/// 状态栏高度
[[UIApplication sharedApplication] statusBarFrame].size.height
/// navigationbar高度
self.navigationController.navigationBar.frame.size.height
/// 我写的高度宏
/// 状态栏高度
#define StatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height
/// 导航栏高度
#define NavigationBarHeight self.navigationController.navigationBar.frame.size.height
/// 状态栏+导航栏高度
#define JWTopBarHeight ([[UIApplication sharedApplication] statusBarFrame].size.height+self.navigationController.navigationBar.frame.size.height)

二十三、CocoaPods的基本操作

记录下CocoaPods的一些基本操作,我脑子有坑,记不住,每次都要百度很烦。

// 搜索三方
pod search
// 创建或打开Podfile文件
vim Podfile
// Podfile文件内容格式,'Test'为你的target的名字
platform :ios,'8.0'
target 'Test' do
#      三方的名字  和     版本号  不填则安装最新的
pod 'MJExtension', '~> 3.0.13'
end
// 添加新的三方,先修改Podfile文件,然后
pod install
// 跟新三方库
pod update
// 删除添加过的三方库,直接修改Podfile文件,删掉 “pod '需要删除三方'  ” 一行,然后 pod instal 或者 pod update

二十四、UITableView刷新cell高度,且不重新加载cell

方法很简单,只需要UITableView调用以下两个方法:

- (void)beginUpdates;
- (void)endUpdates;

这两个方法是必须是成对出现的,调用后会UITableView的代理会重新走- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;方法,加载cell高度,且不会走- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;方法。
关于这两个方法,这里有介绍

二十五、在 石家庄三秒软件科技有限公司 的感受

在这我也努力过、拼搏过、奋斗过,但是看不到希望。
1、重复的、机械式的工作让人颓废和反感,完全得不到技术上的成长;
2、我不反感加班,我也愿意加班,但是强制加班、把上班时间的工作强行挪到下班时间,不参加就扣100,这就过分了;
3、多次无故晚发工资,没有任何解释,问财务,财务说质量人员没有出绩效表,发不了;问质量,说上个月绩效没有核对出来,马上就出来了,在等一天,每次问都是这样,结果从15号等到了30号,我想问问你把员工当傻子吗?上个月的绩效,从月初就应该开始核对,我不知道公司的业务是多么复杂,需要一个月来核对,领导的解释是这是在李总考验员工,能不能经住金钱的考验,这样才能保证公司壮大了员工不会被金钱购买,心里有句***不知当讲不当讲,这或许是压倒骆驼的最后一根稻草;
4、唯一让我留恋的就是有些领导,他们很好,很喜欢在他们手下干活。
5、感谢公司让我成长,也非常抱歉不能和公司继续成长,江湖甚远,有缘再见。

二十六、人走向前

新公司入职以两周了,越发的感觉辞职的决定是明确的,感悟颇深。

二十七、UIButton文字内容太长,修改省略号位置

只需要修改button的titleLabel的lineBreakMode属性

 button.titleLabel.lineBreakMode =  NSLineBreakByTruncatingTail;

二十八、UINavigationItem上的titleView位置问题

先记录下,改天总结
主要是translatesAutoresizingMaskIntoConstraints属性,

// 不使用AutoLayout机制
self.titleView.translatesAutoresizingMaskIntoConstraints = NO;

二十九、关于Masonry

这篇文章记录的很全,iOS自动布局框架-Masonry详解,学习下。

三十、关于通讯录权限判断

看到一篇文章很好,分析了应该使用那种方式。
AddressBook权限的判断

ABAuthorizationStatus authorizationStatus = ABAddressBookGetAuthorizationStatus();
// 判断授权状态
if (authorizationStatus == kABAuthorizationStatusNotDetermined) {
    // 首次访问通讯录
    // 请求授权
    ABAddressBookRef addressBookRef =  ABAddressBookCreate();
    __weak typeof(self) weakSelf = self;
    ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
        if (granted) {
                // 授权成功 获取通讯数据
        } else {
                // 授权失败
        }
    });
}else if (authorizationStatus == kABAuthorizationStatusDenied || authorizationStatus == kABAuthorizationStatusRestricted) {
    // 拒绝授权   或者  未授权,且用户无法更新,如家长控制情况下
}else if (authorizationStatus == kABAuthorizationStatusAuthorized) {
    // 同意授权 获取通讯数据
}

三十一、UILAbel设置了attributedText后省略号不显示问题

2018-04-27总结
因为设置了attributedText后,UIlabellineBreakMode = NSLineBreakByTruncatingTail就会失效。参考如下:

self.contentLabel.attributedText = attributedString;
// 重新设置
self.contentLabel.lineBreakMode = NSLineBreakByTruncatingTail;

亲测有效,同理一些其他因为设置属性字符串导致的问题,也可以如此解决,例如文字居中等。

三十二、iOS开发学习路线

2018-05-15
今天逛简书看到的,感觉很发人深省,记录下。

三十三、用NSLayoutConstrain给控件做了约束以后,如何执行一定的UIView动画呢?

2018-05-15 原文地址

// 在修改了约束以后,只要执行下边的代码,就能做动画效果   
[UIView animateWithDuration:2.0 animations:^{
     [修改了约束的View    layoutIfNeeded];   
}];

三十四、淡入淡出切换rootViewController

原文地址 亲测有效,无脑搬运记载

// 登陆后淡入淡出更换rootViewController
- (void)restoreRootViewController:(UIViewController *)rootViewController { 
    typedef void (^Animation)(void); 
    UIWindow* window = [UIApplication sharedApplication].keyWindow; 
    rootViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; 
    Animation animation = ^{ 
        BOOL oldState = [UIView areAnimationsEnabled];
        [UIView setAnimationsEnabled:NO]; 
        [UIApplication sharedApplication].keyWindow.rootViewController = rootViewController; 
        [UIView setAnimationsEnabled:oldState]; 
    }; 
    [UIView transitionWithView:window duration:0.5f options:UIViewAnimationOptionTransitionCrossDissolve animations:animation completion:nil]; 
}

未完待续。。。

上一篇下一篇

猜你喜欢

热点阅读