美文网首页
iOS13适配

iOS13适配

作者: 荷码人生 | 来源:发表于2019-09-29 09:31 被阅读0次
    1. 状态栏相关
      获取状态栏:
    if (@available(iOS 13.0, *)) {
            UIView *_localStatusBar = [[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager performSelector:@selector(createLocalStatusBar)];
            UIView * statusBar = [_localStatusBar performSelector:@selector(statusBar)];
    // 注意此代码不生效
    //           [statusBar drawViewHierarchyInRect:statusBar.bounds afterScreenUpdates:NO];
            [statusBar.layer renderInContext:context];
    
    } else {
            // Fallback on earlier versions
    }
    
    1. 控制器的 modalPresentationStyle 默认值变了:
      UIModalPresentationStyle 新增加:UIModalPresentationAutomatic;
      原来效果的模式:
      self.modalPresentationStyle = UIModalPresentationFullScreen;
      注意:当modalPresentationStyle = UIModalPresentationAutomatic
      在关闭模态的时候,不会调用apper等方法。
    2. MPMoviePlayerController 在iOS 13更改为AVKit--->AVPlayerViewController
      可参考链接 Demo
    3. iOS 13 DeviceToken有变化‼️
      (第三方推送都是将DeviceToken原始数据丢进去,具体的解析都是第三方内部处理)
    
    /**************不规范的做法***********************/
    
    NSString *dt = [deviceToken description];
    dt = [dt stringByReplacingOccurrencesOfString: @"<" withString: @""];
    dt = [dt stringByReplacingOccurrencesOfString: @">" withString: @""];
    dt = [dt stringByReplacingOccurrencesOfString: @" " withString: @""];
    
    /**************解决犯法(1)***********************/
    
    NSMutableString *deviceTokenString = [NSMutableString string];
    const char *bytes = deviceToken.bytes;
    NSInteger count = deviceToken.length;
    for (int i = 0; i < count; i++) {
        [deviceTokenString appendFormat:@"%02x", bytes[i]&0x000000FF];
    }
    /**************解决犯法(2)友盟提供***********************/
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
        if (![deviceToken isKindOfClass:[NSData class]]) return;
        const unsigned *tokenBytes = [deviceToken bytes];
        NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
                              ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
                              ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
                              ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
        NSLog(@"deviceToken:%@",hexToken);
    }
    
    1. Sign in with Apple (提供第三方登录的注意啦⚠️)
    2. 即将废弃的 LaunchImage-->launchScreen(AutoLayout+SizeClass)
      再补充一点,在使用 LaunchScreen的时候,里面用到的图片资源,最好别放在 xcassets 里面,不然在你修改图片后,你会发现真机上并不会生效。
    3. 注意⚠️,iOS 13 通过 KVC 方式修改私有属性,有 Crash 风险,谨慎使用!
    (1)UISearchBar的更改
    /*******************使用代码*******************/
    [self setValue:@"xxx " forKey:@"_cancelButtonText"];
    /*******************更换成*******************/
    - (void)set_cancelButtonText:(NSString *)text
    
    (2)TextField的属性 _placeholderLabel 被禁止访问了------->attributedPlaceholder
    /*******************使用代码*******************/
    [_textField setValue:self.placeholderColor forKeyPath:@"_placeholderLabel.textColor"];
    /*******************错误提示*******************/
    'Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug '' 
    /*****************解决方案*********************/
    NSMutableAttributedString * placeholderString = [[NSMutableAttributedString alloc] initWithString:placeholder attributes:@{NSForegroundColorAttributeName : self.placeholderColor}];
    _textField.attributedPlaceholder = placeholderString;
    /**************************************/
    
    1. TabBar的一些改动,小红点问题
      遍历UITabBarButton的subViews发现只有在TabBar选中状态下才能取到UITabBarSwappableImageView,解决办法是修改为通过UITabBarButton的位置来设置红点的frame。

    2. 黑线处理crash
      之前为了处理搜索框的黑线问题会遍历后删除UISearchBarBackground,在iOS13会导致UI渲染失败crash;
      解决办法是设置UISearchBarBackground的layer.contents为nil

    /****************使用代码**********************/
    public func clearBlackLine() {
            for view in self.subviews.last!.subviews {
                if view.isKind(of: NSClassFromString("UISearchBarBackground")!) {
                    view.backgroundColor = UIColor.white
                    view.layer.contents = nil
                    break
                }
            }
        }
    
    1. 黑夜模式:
    UIColor *dynamicColor =  [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * provider) {
            //使用 provider 判断,有时会出问题
            if(keyWindow.isDark){
                return darkColor;
            }
            return lightColor;
    }];
    
    1. Xcode 11 缺失文件导入位置变更

    Xcode11下 这个目录不存在了

    /****************Xcode11的位置**********************/
    /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/
    

    【变更为】

    /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/
    

    以下位置不需要变动

    /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/
    
    /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/
    
    /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib/
    

    12 .友盟分享 注册新浪平台 崩溃【验证:仅在模拟器上出现】

    这个应该是需要微博官方进行适配了,尝试模拟了 getUniqueStrByUUID 中的相关写法,无果。

    +[_LSDefaults sharedInstance] 崩溃问题

    暂时的处理手段

    @implementation NSObject (Extend)
    + (void)load{
      
      SEL originalSelector = @selector(doesNotRecognizeSelector:);
      SEL swizzledSelector = @selector(sw_doesNotRecognizeSelector:);
      
      Method originalMethod = class_getClassMethod(self, originalSelector);
      Method swizzledMethod = class_getClassMethod(self, swizzledSelector);
      
      if(class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))){
          class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
      }else{
          method_exchangeImplementations(originalMethod, swizzledMethod);
      }
    }
    
    + (void)sw_doesNotRecognizeSelector:(SEL)aSelector{
      //处理 _LSDefaults 崩溃问题
      if([[self description] isEqualToString:@"_LSDefaults"] && (aSelector == @selector(sharedInstance))){
          //冷处理...
          return;
      }
      [self sw_doesNotRecognizeSelector:aSelector];
    }
    
    

    13 . window 变更问题

    在iOS13版本下,App 任意处生成YYTextView均会导致全局的scrollsToTop 回顶功能失效。最终追溯到YYTextEffectWindow类。

    -[UICollectionView scrollViewShouldScrollToTop:] 
    -[UIScrollView _scrollToTopIfPossible:] ()
    -[UIScrollView _scrollToTopFromTouchAtScreenLocation:resultHandler:] ()
    -[UIWindow _scrollToTopViewsUnderScreenPointIfNecessary:resultHandler:]_block_invoke.796 ()
    -[UIWindow _handleScrollToTopAtXPosition:resultHandler:] ()
    //此处能看到有个新鲜的 UIStatusBarManager 是iOS13新增的类,可以看到状态栏的点击事件已经被其接管了。
    //经过实践,出问题的时候该方法也能被正常调用故此排上以上调用栈方法。
    -[UIStatusBarManager _handleScrollToTopAtXPositi
    
    
    开始以为是多个UIScrollView共存时scrollsToTop的设置问题,还有UIScrollViewContentInsetAdjustmentNever的设置问题。结果都不是...
    最终沿着UIScrollView 子类一直查找,找到了YYTextView 其中用到的 YYTextEffectWindow也进入了视野...
    
     >   static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            if (![UIApplication isAppExtension]) {
                one = [self new];
                one.frame = (CGRect){.size = kScreenSize};
                one.userInteractionEnabled = NO;
                //此处能看到 窗口等级是高于状态栏的,但多次尝试等级调整均无果。
                one.windowLevel = UIWindowLevelStatusBar + 1;
                
               //元凶在这里
               //所以,即使关闭了用户交互 但是它竟能够阻挡状态栏的事件,但却对常规Window的事件无任何影响...
                if (@available(iOS 13.0, *)) {
                    //费解的结果...
                    one.hidden = YES;
                }else{
                    one.hidden = NO;
                }
                
                // for iOS 9:
                one.opaque = NO;
                one.backgroundColor = [UIColor clearColor];
                one.layer.backgroundColor = [UIColor clearColor].CGColor;
            }
        });
        return one;
    
        在UIWindow 上使用addSubview添加子视图,需要注意 暗黑模式切换,并不会向子视图下发状态变更。
    

    解决办法:
    获取系统暗黑切换通知(自行实现),然后重写添加到 UIWindow 的子视图 overrideUserInterfaceStyle 为正确的状态。

    1. UIScrollView 滚动条异常偏移
      屏幕旋转可能会触发系统对滚动条的自动修正
      如果没有修改需求,关闭该特性即可
    /*******************代码***********************/
    #ifdef __IPHONE_13_0
            if (@available(iOS 13.0, *)) {
                self.automaticallyAdjustsScrollIndicatorInsets = NO;
            }
    #endif
    
    1. UICollectionView 异常API

    该API 在iOS13下会强制将cell置中,导致上部留白。
    推测,底部应该也会有留白的情况。

    #pragma mark - 修复iOS13 下滚动异常API
    #ifdef __IPHONE_13_0
    - (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated{
        
        [super scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated];
    
        //修复13下 图片滚动位置异常
        //顶部
        if(self.contentOffset.y < 0){
            [self setContentOffset:CGPointZero];
            return;
        }
        //底部
        if(self.contentOffset.y > self.contentSize.height){
            [self setContentOffset:CGPointMake(0, self.contentSize.height)];
        }
    }
    #endif
    
    1. UITableViewCell 异常 【疑似iOS13beta4新出现】[marson 失效问题]
    [self addSubView: viewObjA]
    [self.contentView addSubview:viewObjB]
    上面两种方式,在遇到折叠需求时。设置self.clipsToBounds=YES 可能会有布局异常
    
    //保险的做法
    self.clipsToBounds = YES;  【无效】
    //此处很费解
    self.layer.masksTobounds = YES;  【有效】
    
    疑似布局引擎机制有调整 【有待确定】
    
    在调试中发现,如果代码流是这样一种状态 可能会造成 【约束失效】
    如果遇到诡异问题 需要排查下是否存在约束和绝对布局混用的情况
    
    [viewMain addSubView:viewA];
    [viewMain addSubView:viewB];
    // 更新 viewA 的约束
     [self.imageBackground mas_updateConstraints:^(MASConstraintMaker *make) {
           make.top.mas_equalTo(50);
     }];
    
     //立即更新约束
     [viewA.superview setNeedsUpdateConstraints];
     [viewA.superview updateConstraintsIfNeeded];
     [viewA.superview layoutIfNeeded];
    
    //更新容器约束
    [viewMain mas_updateConstraints:^(MASConstraintMaker *make) {
           make....
     }];
    
    ....
    其它处理逻辑
    ....
    
    // 更新 viewA 的约束 【代码不会生效】
     [self.imageBackground mas_updateConstraints:^(MASConstraintMaker *make) {
           make.top.mas_equalTo(100);
     }];
    
    1. WKWebView 暗黑适配
      要点:
      模式参数通过 UA 传递
      联调中出现加载闪白问题
     webView.opaque = false;
    
    1. 手势影响
      iOS13下,如果在UITextView上附加如拖动手势,会发现如果触点落在UITextView之上极易触发第一响应者。
      实际效果,可对比iOS12之前版本的表现。

    ** 注意这两项即使开启也不会有改善效果**
    gesture.cancelsTouchesInView = YES;
    gesture.delaysTouchesBegan = YES;

    1. NSMonthCalendarUnit 更改为 NSCalendarUnitMonth 的使用;

    2. UISegmentedControl中tintColor失效问题:

    之前的我们设置 tintColor 去除选择颜色以及背景色,在 iOS13 中失效了。

    解决方案:
    (1)selectedSegmentTintColor 设置 选中的颜色,只是更改选中的颜色。
    (2) 去除背景色以及选中的颜色

    #import "UISegmentedControl+Commen.h"
    @implementation UISegmentedControl (Commen)
    
    -(void)tintColorDidChange{
        // UISegmentedControl has changed in iOS 13 and setting the tint
        // color now has no effect.
        if (@available(iOS 13, *)) {
            UIColor * tintColor = [self tintColor];
            UIImage *tintColorImage = [self imageWithColor:tintColor];
            // Must set the background image for normal to something (even clear) else the rest won't work
            [self setBackgroundImage:[self imageWithColor:self.backgroundColor ? self.backgroundColor : [UIColor clearColor]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
            [self setBackgroundImage:tintColorImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
            [self setBackgroundImage:tintColorImage forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
            [self setDividerImage:tintColorImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
        }
    }
    
    - (UIImage *)imageWithColor: (UIColor *)color {
        CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, self.frame.size.height);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [color CGColor]);
        CGContextFillRect(context, rect);
        UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return theImage;
    }
    @end
    

    总结
    以上是我在实际的适配中的遇到的问题,其他的问题,暂未发现。该文章会在实际工作中的持续更新,尽情期待吧...

    相关文章

      网友评论

          本文标题:iOS13适配

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