适配ios13

更新Xcode之后,新项目需求,新建项目发现多了如图1所示两个新的文件SceneDelegate.h和SceneDelegate.m

运行之后发现黑屏,无论是真机还是模拟器都不行,换到iOS12的手机上则可以正常运行。
查看官方文档,SceneDelegate是为了优化启动和实现iPad多任务处理功能(在ipad上同时打开多个窗口)做出的改动,将原本在AppDelegate里的生命周期相关方法和window分离出来
iOS13以前:AppDelegate管理App的生命周期和UI生命周期;
iOS13以后:AppDelegate管理App的生命周期和新增的UISceneSession生命周期,新增SceneDelegate文件来管理UI生命周期和window;
关于解决有两种情况:
1、不开发iPadOS多窗口App
1)将新增的SceneDelegate文件删除
2)删除info.plist文件中Application Scene Manifest选项,如下图所示

3)在AppDelegate中新增window属性,在didFinishLaunchingWithOptions方法中跟往常一样进行相应根控制设置及处理,并删除新增的UISceneSession两个方法

2、需要用到SceneDelegate进行开发或不想删除该文件,且需要适配iOS13以前的版本。
解决核心:添加版本控制

1)AppDelegate中增加window属性,在didFinishLaunchingWithOptions方法中用if (@available(iOS 13.0, *)){}进行版本控制,UISceneSession lifecycle里的两个方法也要添加版本控制,如下图所示

(因为在iOS13以前的系统中,没有SceneDelegate文件,所以还是需要在AppDelegate方法中进行根控制的设置)
2)在SceneDelegate中willConnectToSession方法里进行根控制设置的时候也要添加相应的版本控制,需要注意的是,此处初始化window的时候需要用WindowScene进行初始化,否则黑屏加载不出视图。

其他适配问题:

1、使用presentViewController推出页面,不会全屏,如图

原因:在iOS13之前,VC的modalPresentationStyle属性默认值为UIModalPresentationFullScreen,而在iOS13中改为了UIModalPresentationAutomatic
解决:设置vc.modalPresentationStyle = UIModalPresentationFullScreen;
2、私有KVC使用崩溃
运行之前项目突然崩溃,定位到UITextField 的Placeholder文字颜色设置

[self.phoneTextField setValue:[UIColor colorWithHexString:@"#888888"] forKeyPath:@"_placeholderLabel.textColor"];
[self.passwordTextField setValue:[UIColor colorWithHexString:@"#888888"] forKeyPath:@"_placeholderLabel.textColor"];
[self.registeTextField setValue:[UIColor colorWithHexString:@"#888888"] forKeyPath:@"_placeholderLabel.textColor"];

有两种解决方案:

//方法1:去掉下划线访问placeholderLabel
[self.phoneTextField setValue:[UIColor blueColor] forKeyPath:@"placeholderLabel.textColor"];
[self.phoneTextField setValue:[UIFont systemFontOfSize:20] forKeyPath:@"placeholderLabel.font"];
//方法2:改为修改并赋值属性字符串
NSMutableAttributedString * attributeStr = [[NSMutableAttributedString alloc] initWithString:@"请输入手机号" attributes:@{NSForegroundColorAttributeName : [UIColor redColor], NSFontAttributeName : [UIFont systemFontOfSize:14.0f]}];
self.phoneTextField.attributedPlaceholder = attributeStr;

3、隐藏tabbar上方黑色横线
由于之前的[UIImage new]方法已经不奏效,且在iOS13之后引入了UITabBarAppearance,所以需要修改为

//去除顶部横线
    if (@available(iOS 13.0, *)) {
        UITabBarAppearance * tabbarAppearance = self.standardAppearance;
        tabbarAppearance.shadowImage = [UIImage imageWithColor:[UIColor clearColor]];
        tabbarAppearance.backgroundImage = [UIImage imageWithColor:[UIColor clearColor]];
        self.standardAppearance = tabbarAppearance;
    } else {
        [self setBackgroundImage:[UIImage imageWithColor:[UIColor clearColor]]];
        [self setShadowImage:[UIImage imageWithColor:[UIColor clearColor]]];
    }

其中[UIImage imageWithColor:[UIColor clearColor]是自定义UIImage分类方法 -- 根据颜色生成图片方法,self为继承于UITabBar的自定义tab,如果引入相应不同项目的时候需要自己做相应改动。附上根据颜色生成图片的方法:

#import "UIImage+LSImageWithColor.h"
@implementation UIImage (LSImageWithColor)

+ (UIImage *)imageWithColor:(UIColor *)color {
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}

@end

4、UIWebView彻底弃用
iOS13上,苹果在UIWebView的使用上明确标注了仅支持iOS2~iOS12的系统,项目中有用到UIWebView的需要全部替换成WKWebView,如果需要适配 iOS 7 的可以通过 openURL 的方式在 Safari 打开。如果没有修改,提交审核将会不通过!

5、三方SDK更新
各SDK(友盟、微信等)都根据iOS13进行了更新,有用到的需要去更新最新的SDK。

6、暗黑适配
1、图片适配
如果项目中有需要适配暗黑模式的图片,可以在Assets.xcassets中设置,具体需要什么样式自己根据项目情况设置

2、UIColor适配
iOS13之后UIColor增加了两个初始化方法来动态创建UIColor:

//类方法
+ (UIColor *)colorWithDynamicProvider:(UIColor * (^)(UITraitCollection *traitCollection))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchOS);
//实例方法
- (UIColor *)initWithDynamicProvider:(UIColor * (^)(UITraitCollection *traitCollection))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);

当系统切换模式的时候,会自动触发这两个方法来动态修改控件颜色,所以可以根据需要使用这两种方法来进行颜色设置,一般写在基类或者UIColor分类中。

//UIColor分类中增加方法
+ (UIColor *)colorWithLightColor:(UIColor *)color withDarkColor:(UIColor *)darkColor{
    if (@available(iOS 13.0, *)) {
       UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
            if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
                return darkColor;
            }
            return color;
        }];
        return dyColor;
    }
    return color;
}

//调用
self.view.backgroundColor = [UIColor colorWithLightColor:[UIColor whiteColor] withDarkColor:[UIColor blackColor]];

iOS13之后系统也提供了一些动态的颜色,如果直接设置提供的那些动态颜色,则不需要使用上面的方法,照常直接设置即可,系统会自动更改颜色,如:labelColor,systemBrownColor等。

3、CGColor适配
CGColor在iOS13之后依然只能表示一种颜色,所以在切换模式后直接返回当前页面时,设置的CGColor并不会动态改变,此时需要调用监听模式切换的方法:
在用到CGColor的VC中重写-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection方法,将layer颜色设置重新写一遍

-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection{
    [super traitCollectionDidChange:previousTraitCollection];
    self.logoutBtn.layer.borderColor = [UIColor colorWithHexString:@"#d6d7dc" withDarkHexString:@"#000000"].CGColor;
}

注:这个方法是重写一遍layer颜色设置,而不是只在该方法中设置颜色,因为该方法是在切换模式的时候触发,如果没有切换模式,也没有在其他地方设置颜色,那么你将得不到颜色。

4、设置单个VC的模式

if (@available(iOS 13.0, *)) {
        [self setOverrideUserInterfaceStyle:UIUserInterfaceStyleDark];
    } else {

    }

仅限于当前VC,推出或返回的VC依然是跟随系统模式。

7、关于LaunchImage
wwdc2019中说在2020年4月之后,所有支持iOS13的App必须提供LaunchScreen.storyboard,否则无法提交到 App Store。
设置步骤:
1)将启动图拖入Assets.xcassets中
2)在LaunchScreen.storyboard中拖入ImageView,设置全屏约束,设置图片,完成
注意:
1)如果运行没有出现启动图,是因为缓存问题,删除App重新运行,再不行,重启模拟器即可
2)真机使用Xcode安装了app,设置启动页之后上传AppStore审核通过,在AppStore下载app之前最好先卸载掉原先的,否则会出现启动页虽然能成功显示,但是在显示之前还有一小段时间显示白屏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章