运行之后发现黑屏,无论是真机还是模拟器都不行,换到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选项,如下图所示
2、需要用到SceneDelegate进行开发或不想删除该文件,且需要适配iOS13以前的版本。
解决核心:添加版本控制
(因为在iOS13以前的系统中,没有SceneDelegate文件,所以还是需要在AppDelegate方法中进行根控制的设置)
2)在SceneDelegate中willConnectToSession方法里进行根控制设置的时候也要添加相应的版本控制,需要注意的是,此处初始化window的时候需要用WindowScene进行初始化,否则黑屏加载不出视图。
其他适配问题:
1、使用presentViewController推出页面,不会全屏,如图
解决:设置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之前最好先卸载掉原先的,否则会出现启动页虽然能成功显示,但是在显示之前还有一小段时间显示白屏。
8、关于UISegmentedControl
1、设置UISegmentedControl的选中段背景色使用新属性selectedSegmentTintColor,以前的tintColor不起作用:
if (@available(iOS 13.0, *)) {
segement.selectedSegmentTintColor = [UIColor orangeColor];
} else {
// Fallback on earlier versions
segement.tintColor = [UIColor orangeColor];
}
2、设置圆角
以前的segement.layer.cornerRadius = 8;没有效果,需要重写UISegmentedControl的layoutSubviews方法来设置圆角:
- (void)layoutSubviews
{
[super layoutSubviews];
self.layer.cornerRadius = 8;
}
另外如果要设置segement的背景图片,需要Normal和Selected两种状态都设置,不然不起效果(这个不是新特性,就是个小tip,我设置的时候没注意这点,一直不起作用,看过解释才知道):
[segement setBackgroundImage:[UIImage imageNamed:@""] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[segement setBackgroundImage:[UIImage imageNamed:@""] forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
(目前项目中出现的问题大致就这些,其他问题欢迎补充)
关于更新:
2020.04.15 在其他适配问题的第6点中补充暗黑模式适配;
2021.12.29 在其他适配问题中新增UISegmentedControl适配;