iOS 13适配填坑总结

前言

  前段时间苹果发布了最新系统iOS 13,开发者当然避免不了去适配最新的系统版本,以下我总结了在适配过程中遇到的问题以及坑。

1、获取当前控制器

  我在适配iOS 13之前获取当前控制器的方法是这样的

- (UIViewController *)currentViewController {
   UIViewController *result = nil;
    UIWindow *keyWindow = [UIApplication sharedApplication].delegate.window;
    if (keyWindow.windowLevel != UIWindowLevelNormal) {
        NSArray *windows = [UIApplication sharedApplication].windows;
        for (UIWindow *tempWindow in windows) {
            if (tempWindow.windowLevel == UIWindowLevelNormal) {
               keyWindow = tempWindow;
                 break;
             }
         }
     }
   id nextResponder = [[keyWindow.subviews firstObject] nextResponder];
    if ([nextResponder isKindOfClass:[UITabBarController class]]) {
        UITabBarController *tabBarController = (UITabBarController*)nextResponder;
        result = tabBarController.selectedViewController;
       if ([result isKindOfClass:[UINavigationController class]]) {
            UINavigationController *naviC = (UINavigationController*)result;
            result = naviC.visibleViewController;
         }
    } else if ([nextResponder isKindOfClass:[UINavigationController class]]) {
        UINavigationController *naviC = (UINavigationController*)nextResponder;
        result = naviC.visibleViewController;
    } else if ([nextResponder isKindOfClass:[UIViewController class]]) {
        result = (UIViewController*)nextResponder;
   } else {
        result = keyWindow.rootViewController;
     }
     
    return result;
 }

打断点发现:

image.png

keywindownextResponder居然在iOS 13 中居然也变成了UIWindow
所以我们可以通过绕过nextResponder来获取当前控制器:

-(UIViewController *)currentViewController{
    UIWindow *window = [UIApplication sharedApplication].delegate.window;
    NSLog(@"window level: %.0f", window.windowLevel);
    if (window.windowLevel != UIWindowLevelNormal) {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for (UIWindow * tmpWin in windows) {
            if (tmpWin.windowLevel == UIWindowLevelNormal) {
                window = tmpWin;
                break;
            }
        }
    }
    
    //从根控制器开始查找
    UIViewController *rootVC = window.rootViewController;
    UIViewController *activityVC = nil;
    
    while (true) {
        if ([rootVC isKindOfClass:[UINavigationController class]]) {
            activityVC = [(UINavigationController *)rootVC visibleViewController];
        } else if ([rootVC isKindOfClass:[UITabBarController class]]) {
            activityVC = [(UITabBarController *)rootVC selectedViewController];
        } else if (rootVC.presentedViewController) {
            activityVC = rootVC.presentedViewController;
        }else {
            break;
        }
        
        rootVC = activityVC;
    }
    
    return activityVC;
}

解决。

2、UIWebView的执行JS脚本方法回调线程问题

  在iOS 13之前中用JSContext执行脚本方法回调的block是在主线程的,可以之间在里面修改UI布局,但是在iOS 13中突然就崩溃了,我在调试中发现了这个回调block居然不在主线程了,崩溃的原因也是因此。

image.png

image.png

临时解决方法是加一个安全线程的调用:

#define dispatch_main_async_safe(block)\
    if ([NSThread isMainThread]) {\
        block();\
    } else {\
        dispatch_async(dispatch_get_main_queue(), block);\
    }

首先声明这个方法只是临时阻止UIWebViewcrash的一种临时方法,本人并不建议这么做,更好的的方法是更换WKWebView,因为UIWebView在iOS 12就已经被废弃。

image.png

3、暗黑模式(Dark Model)

两种方法:
1)直接全局关闭暗黑模式(不建议)
info.plist中加入:key 为User Interface Style value类型为String值为Light可直接全局禁用暗黑模式
2)根据风格适配
我借鉴了这篇文章

4、UIViewController的UIModalPresentationStyle属性

在iOS 13未适配的时候突然发现present出来的控制器样式变了,在查看了相关属性的情况之后发现了UIModalPresentationStyle新增了一个枚举值UIModalPresentationAutomatic在iOS 13之后控制的默认值就是这个,要想恢复之前的模态跳转样式需要设置控制器UIModalPresentationStyleUIModalPresentationFullScreen就好:

if (@available(iOS 13.0, *)) {//iOS 13 默认不使用 UIModalPresentationFullScreen 模式
            self.modalPresentationStyle =  UIModalPresentationFullScreen; 
}
5、UITextField的leftview

在iOS 13中突然发现我的UITextfield leftview显示有点怪,然后发现如果直接给 textfield.leftView 赋值一个 UILabel 对象,他的宽高会被 sizeToFit。解决方法:给label套一层UIView的父视图在设置leftview。解决

6、Push推送获取的token的变化

在iOS 13的系统版本中,token的格式发生了变得,导致不能按照iOS13之前的处理方法去处理然后再上传服务器。

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    DBLOG_FUN;
   NSString *_deviceToken = @"";
   if (@available(iOS 13.0, *)) {
      if (![deviceToken isKindOfClass:[NSData class]]) return;
      const unsigned *tokenBytes = [deviceToken bytes];
      _deviceToken = [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])];
      [[DataStore sharedStore] setDeviceToken:_deviceToken];
      DBLOG(@"_deviceToken:%@", _deviceToken);
   }else if([deviceToken.description length] > 0) {
        NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"<>"];
        _deviceToken = [deviceToken.description stringByTrimmingCharactersInSet:set];
        _deviceToken = [_deviceToken stringByReplacingOccurrencesOfString:@" " withString:@""];
        [[DataStore sharedStore] setDeviceToken:_deviceToken];
        DBLOG(@"_deviceToken:%@", _deviceToken);
    }
}
7、UITextfield通过KVC修改placeholderlabel方法

在iOS 13中通过以下方法修改UITextfield的placeholder会发生crash:

// 使用的私有方法
[_textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];

解决方法有两种:
1)把前面的下划线去掉(不建议)

[_textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];

2)通过attributedPlaceholder设置(建议)

_textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"输入"attributes:@{NSForegroundColorAttributeName: [UIColor redColor]}];
待续。。。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容

  • iOS 13 支持适配的机型 iPhone X、iPhone XR、iPhone XS、iPhone XS Max...
    不成活不疯魔阅读 44,007评论 22 131
  • crash 1.使用PHCachingImageManager获取iCloud图片会crash PHImageMa...
    wu大维阅读 1,621评论 0 2
  • 我善良 我以为善良就是爱 我以善之念,以爱之名 做了一切我以为对你好的事 你却说我不爱,乃至说我是恶是坏 善良不是...
    白光行者阅读 93评论 0 4
  • 怎 奈 倒头睡醒,发现才11点半。这夜里的第一醒又没有把握好分寸,至少早了半个小时。 我瞧...
    微云一抹阅读 1,042评论 37 12
  • 小A是个内敛女,但凡这样的内敛女,一旦动了真感情,就会陷得很深,难以自拔。 与他相遇在一次朋友的聚会,初次见面,大...
    木木晨光阅读 265评论 2 0