iOS13 新特性小结
对于开发者来说 iOS13做了些许变更 现在简介下自己在项目中遇到的问题,可能不全面,只是遇到的问题及处理办法
一、Modal默认样式发生变化 iOS13之前默认为UIModalPresentationFullScreen 13之后变为UIModalPresentationAutomatic
typedef NS_ENUM(NSInteger, UIModalPresentationStyle) { UIModalPresentationFullScreen = 0, UIModalPresentationPageSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos), UIModalPresentationFormSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos), UIModalPresentationCurrentContext API_AVAILABLE(ios(3.2)), UIModalPresentationCustom API_AVAILABLE(ios(7.0)), UIModalPresentationOverFullScreen API_AVAILABLE(ios(8.0)), UIModalPresentationOverCurrentContext API_AVAILABLE(ios(8.0)), UIModalPresentationPopover API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(tvos), UIModalPresentationBlurOverFullScreen API_AVAILABLE(tvos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(watchos), UIModalPresentationNone API_AVAILABLE(ios(7.0)) = -1, UIModalPresentationAutomatic API_AVAILABLE(ios(13.0)) = -2, };
适配方法:
1、明确指定控制器的modalPresentationStyle为UIModalPresentationFullScreen;
cameraController.modalPresentationStyle = UIModalPresentationFullScreen;
2、为UIViewController扩展该方法(本质是重写modalPresentationStyle属性的get方法),这样所有地方就直接生效了,不用一处一处修改,当然私有pod库中的还是要自己修改
/* Defines the presentation style that will be used for this view controller when it is presented modally. Set this property on the view controller to be presented, not the presenter. If this property has been set to UIModalPresentationAutomatic, reading it will always return a concrete presentation style. By default UIViewController resolves UIModalPresentationAutomatic to UIModalPresentationPageSheet, but system-provided subclasses may resolve UIModalPresentationAutomatic to other concrete presentation styles. Participation in the resolution of UIModalPresentationAutomatic is reserved for system-provided view controllers. Defaults to UIModalPresentationAutomatic on iOS starting in iOS 13.0, and UIModalPresentationFullScreen on previous versions. Defaults to UIModalPresentationFullScreen on all other platforms. */ @property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle API_AVAILABLE(ios(3.2));
// 适配iOS13
- (UIModalPresentationStyle)modalPresentationStyle {
// 适配iOS13系统下 RN弹窗内容被遮挡
if ([self isKindOfClass:NSClassFromString(@"RCTModalHostViewController")]) {
return UIModalPresentationOverCurrentContext;
}else {
return UIModalPresentationFullScreen;
}
}
二、部分私有API结构发生变化,之前的访问方式会导致崩溃
项目中我们一直会通过KVC去修改系统中的私有API的一些属性,比如获取搜索框的_searchField修改色值字体等等,在iOS13之后这样是不被允许的,用xocde11打包在iOS13系统下直接会崩溃。
适配方法:
1、用低版本xcode打包(xocde11以下版本),这样在iOS13系统下是不会崩溃的,但是不建议这么做
2、不再访问私有属性
_searchField 获取方式
iOS13对外暴露了searchTextField 属性 直接获取就行
@interface UISearchBar (UITokenSearch) @property (nonatomic, readonly) UISearchTextField *searchTextField; @end
UITextField *searchTextField; if (@available(iOS 13.0, *)) { searchTextField = searchBar.searchTextField; }else { searchTextField = [searchBar valueForKey:@"_searchField"]; }
StatusBar 获取方式
UIView *statusBar = [UIView new]; if (@available(iOS 13.0, *)) { statusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame]; [[UIApplication sharedApplication].keyWindow addSubview:statusBar]; } else { statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"]; }
三、PHPhotoLibrary 的performChanges 与 performChangesAndWait 方法
先说我遇到的问题:我是先拍照然后保存到相册,在iOS13之前使用performChanges这个方法能够正常,但在iOS13之后发现保存到相册后回调失效,导致的效果就是拍摄后卡到那里没反应。
一般我们在操作到相册的时候回用到这个类,比如存储照片或者视频到相册之类的。第一个方法是异步操作,第二个方法是同步操作。在iOS13之前使用performChanges是没有问题的,可以在回调中做相关操作,但在iOS13之后回调会不好使,所以必须在performChangesAndWait之后做相关操作。
// handlers are invoked on an arbitrary serial queue // Nesting change requests will throw an exception - (void)performChanges:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler; - (BOOL)performChangesAndWait:(dispatch_block_t)changeBlock error:(NSError *__autoreleasing *)error;
适配方法:
将performChanges方法替换为performChangesAndWait方法,同时将performChanges回调中的操作放到performChangesAndWait执行之后
四、UIWebView将废弃
大家对UIWebView都是有情怀的,之前在iOS8的时候引入WebKit框架提供WKWebView,性能较UIWebView有很大的提升,但也改变了很多,比如UIWebView是通过外联协议实现事件交互,但WKWebView是通过消息机制实现的,我厂一直未替换的原因就在于此,但这把看来苹果是铁了心要让大家替换了,所以就用WKWebView吧
UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0)) API_UNAVAILABLE(tvos, macos) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate>
#if TARGET_OS_IPHONE WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0)) @interface WKWebView : UIView #else WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0)) @interface WKWebView : NSView #endif
适配方法:
使用WKWebView代替,但如果涉及到与原生事件交互的话,可能需要点工作量,但这是趋势。
五、暗黑模式
将同一个资源,创建出两种模式的样式。系统根据当前选择的样式,自动获取该样式的资源。
每次系统更新样式时,应用会调用当前所有存在的元素调用对应的一些重新方法,进行重绘视图,可以在对应的方法做相应的改动。
适配方法:
1、适配暗黑模式
1-1、创建一个Assets文件(或在现有的Assets文件中)
1-2、新建一个图片资源文件(或者颜色资源文件、或者其他资源文件)
1-3、选中该资源文件, 打开 Xcode ->View ->Inspectors ->Show Attributes Inspectors (或者Option+Command+4)视图,将Apperances 选项 改为Any,Dark
1-4、执行完第三步,资源文件将会有多个容器框,分别为 Any Apperance 和 Dark Apperance. Any Apperance 应用于默认情况(Unspecified)与高亮情况(Light), Dark Apperance 应用于暗黑模式(Dark)
1-5、代码默认执行时,就可以正常通过名字使用了,系统会根据当前模式自动获取对应的资源文件
2、关闭暗黑模式
2-1、配置plist文件: 在Info.plist 文件中,添加UIUserInterfaceStyle key 名字为 User Interface Style 值为String,将UIUserInterfaceStyle key 的值设置为 Light。
2-2、代码关闭黑暗模式 强制关闭暗黑模式
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 if(@available(iOS 13.0,*)){ self.window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight; } #endif
六、UISegmentedControl发生变化
UISegmentedControl iOS13之前默认选中样式是带边框、且选中是蓝色的、只能点击选中。iOS13之后 默认是无边框、且字体色值变为灰色、且可以滑动选中
适配方法:
// 设置默认选中色值 [segmentedControl setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:ICOME_COLOR_3480FF, NSForegroundColorAttributeName,[UIFont boldSystemFontOfSize:15.0f],NSFontAttributeName, nil] forState:UIControlStateSelected]; // 添加边框 [segmentedControl borderWidth:1 andBorderColor:[UIColor whiteColor]];
-(instancetype)borderWidth:(CGFloat)borderWidth andBorderColor:(UIColor*)borderColor
{
CALayer* layer=self.layer;
layer.borderWidth=borderWidth;
layer.borderColor=borderColor.CGColor;
return self;
}