iOS之iOS13适配总结

作者: 枫叶无处漂泊 | 来源:发表于2020-04-01 18:04 被阅读0次

    前言

    随便iOS开发开始更新变成Xcode11,适配iOS13变成了现在的当务之急。

    新特性适配

    一、新添加的Dark Mode

    iOS 13 推出暗黑模式,UIKit 提供新的系统颜色和 api 来适配不同颜色模式,xcassets 对素材适配也做了调整,具体适配可见: Implementing Dark Mode on iOS

    切换、修改当前 UIViewController 或 UIView的模式。只要设置了控制器为暗黑模式,那么它子view也会对应的修改。

    • 只修改当前UIViewController或UIView的模式。
    • 只要设置了控制器为暗黑模式,那么它子view也会对应的修改。

    代码如下:

    if (@available(iOS 13.0, *)) {
       self.overrideUserInterfaceStyle =  UIUserInterfaceStyleDark;//UIUserInterfaceStyleLight
    } else {
        // Fallback on earlier versions
    }
    

    注意当我们在window上设置 overrideUserInterfaceStyle的时候,就会影响 window下所有的controller,view,包括后续推出的 controller。

    二、使用KVC访问私有变量已发崩溃

    iOS13之后就不能通过KVC访问修改私有属性,不然就会找不到这个key,从而引发崩溃。

    目前搜集到的KVC访问权限引发崩溃的方法:

    1. UIApplication -> _statusBar
    2. UITextField -> _placeholderLabel
    3. UITabBarButton -> _info
    4. UISearchBar -> _searchField
    5. UISearchBar -> _cancelButton
    6. UISearchBar -> _cancelButtonText
    7. UISearchBar -> UISearchBarBackground

    1、UIApplication -> _statusBar 获取状态栏崩溃

    在iOS13上获取状态栏statusBar,不能直接用KVC。要使用performSelector

    UIStatusBarManager *statusBarManager = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager;
    UIView *statusBar;
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wundeclared-selector"
    if([statusBarManager respondsToSelector:@selector(createLocalStatusBar)]) {
                
        UIView *localStatusBar= [statusBarManager performSelector:@selector(createLocalStatusBar)];
        if ([localStatusBar respondsToSelector:@selector(statusBar)]) {
                    
            statusBar = [localStatusBar performSelector:@selector(statusBar)];
        }    
    }
    
    

    适配的时候就是iOS13和非iOS13

    if(@available(iOS 13.0, *)) {
    
        //上面获取statusBar代码        
    } else {
        
        UIView *statusBar = [[UIApplication sharedApplication] 
        valueForKey:@"statusBar"];
    
    }
    
    

    2、UITextField -> _placeholderLabel

    在iOS13 UITextField通过KVC来获取_placeholderLabel会引发崩溃。

    //在ios13使用会引发崩溃
    [self.textField setValue:self.placeholderColor 
    forKeyPath:@"_placeholderLabel.textColor"];
    
    

    崩溃如下:

    'Access to UITextField's _placeholderLabel ivar is prohibited. 
    This is an application bug' 
    
    

    解决方案:UITextField有个attributedPlaceholder的属性,我们可以自定义这个富文本来达到我们需要的结果。

    NSMutableAttributedString *placeholderString = [[NSMutableAttributedString alloc] initWithString:placeholder 
    attributes:@{NSForegroundColorAttributeName : self.placeholderColor}];
    _textField.attributedPlaceholder = placeholderString;
    
    

    3、UISearchBar 黑线处理导致崩溃

    iOS13之前为了处理搜索框的黑线问题,通常会遍历searchBar的 subViews,找到并删除UISearchBarBackground。

    在 iOS13 中这么做会导致UI渲染失败,然后直接崩溃,崩溃信息如下:

    erminating app due to uncaught exception'NSInternalInconsistencyException', reason: 'Missing or detached view for search bar layout'

    解决方案:修改方法为:设置 UISearchBarBackground 的 layer.contents 为 nil

    for (UIView *view in _searchBar.subviews.lastObject.subviews) {
       if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
            view.layer.contents = nil;
            break;
        }
     } 
    

    4、iOS UISearchBar通过kvc获取_cancelButtonText、_cancelButton、_searchField引发崩溃。

    先说一下_searchField来说明的解决方案。

    在iOS13之前,我们通过"_searchField"来获取UISearchTextField来修改一些属性。

     UITextField *searchFiled = [self valueForKey:@"_searchField"];
    

    但在iOS13会引发崩溃,解决方案就是在iOS13中引入了名为searchTextField的属性。

    @property (nonatomic, readonly) UISearchTextField *searchTextField;
    

    查看一下UISearchTextField

    UIKIT_CLASS_AVAILABLE_IOS_ONLY(13.0)
    @interface UISearchTextField : UITextField
    ///功能省略
    @end
    

    发现UISearchTextField继承UITextField,代码实现:

    UITextField *searchField;
     if(@available(iOS 13.0, *)) {
        //UISearchBar的self.searchTextField属性是readonly,不能直接用
        searchField =  self.searchTextField; 
     } else {
        searchField = [self valueForKey:@"_searchField"];
     }
    

    三、presentViewController 默认弹出样式

    • 苹果将 UIViewController 的 modalPresentationStyle 属性的默认值改成了新加的一个枚举值 UIModalPresentationAutomatic,对于多数 UIViewController,此值会映射成 UIModalPresentationPageSheet。
    • iOS13系统的默认样式是: UIModalPresentationAutomatic
    • iOS12及以下系统的默认样式是:UIModalPresentationFullScreen;

    想要改成以前默认的样式

    - (UIModalPresentationStyle)modalPresentationStyle {
        return UIModalPresentationFullScreen;
    }
    
    

    四、AVPlayerViewController 替换MPMoviePlayerController

    在 iOS 9 之前播放视频可以使用 MediaPlayer.framework 中的MPMoviePlayerController类来完成,它支持本地视频和网络视频播放。但是在 iOS 9 开始被弃用,如果在 iOS 13 中继续使用的话会直接抛出异常:

    'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.' 
    

    解决方案:
    既然不能再用了,那只能换掉了。替代方案就是AVKit里面的那套播放器。

    五、废弃UIWebview 改用 WKWebView

    iOS13 开始苹果将 UIWebview 支持的系统(iOS2.0-iOS12.0),目前提交苹果应用市场(App Store)会发送邮件提示你在下一次提交时将应用中UIWebView的api移除。

    虽然暂时没有强制必须替换WKWebView,但是在iOS13开始UIWebView已是废弃的API,所以还是越早换越好。

    六、iOS13 获取window适配

    在iOS13通过UIWindowScene的方式获取window

    UIWindow* window = nil;
    if (@available(iOS 13.0, *)) {
        for (UIWindowScene* windowScene in [UIApplication sharedApplication].connectedScenes) {
            if (windowScene.activationState == UISceneActivationStateForegroundActive) {
                window = windowScene.windows.firstObject;
                break;
            }
        }
    }else{
        window = [UIApplication sharedApplication].keyWindow;
    }
    
    

    七、iOS13 废弃LaunchImage

    从iOS8的时候,苹果就引入了LaunchScreen,我们可以设置 LaunchScreen来作为启动页。当然,现在你还可以使用LaunchImage来设置启动图。

    但是从2020年4月开始,所有使⽤ iOS13 SDK的 App将必须提供 LaunchScreen,LaunchImage即将退出历史舞台。使用LaunchScreen有点:

    • 不需要单独适配种屏幕尺寸的启动图
    • LaunchScreen是支持AutoLayout+SizeClass的,所以适配各种屏幕都不在话下

    七、iOS13 适配UISegmentedControl

    默认样式变为白底黑字,如果设置修改过颜色的话,页面需要修改。
    如下图:

    iOS13-segControl.png

    其次设置选中颜色的tintColor属性在iOS13已经失效,所以在iOS13新增新增了selectedSegmentTintColor 属性用以修改选中的颜色。

    适配代码如下:

    if ( @available(iOS 13.0, *)) {
        self.segmentedControl.selectedSegmentTintColor = [UIColor yellowcolor];
    } else {
        self.segmentedControl.tintColor = [UIColor yellowcolor];
    }
    
    

    相关文章

      网友评论

        本文标题:iOS之iOS13适配总结

        本文链接:https://www.haomeiwen.com/subject/jqgauhtx.html