iOS13适配(踩坑)不完全汇总

1

通过KVC获取/访问私有属性无效

iOS13不允许通过valueForKey:valueForKeyPath:setValue: forKey: setValue: forKeyPath:获取或设置私有属性;以上KVC方法,使用Xcode11及之后版本编译会崩溃;Xcode10及之前版本虽不会崩溃,但无效;
之前有使用私有属性的地方,均需另辟蹊径:

  • 设置UISearchBar的textField
    在13中把UISearchBar中的textField直接暴露给开发者使用,无需在通过KVC获取
UITextField *searchTextField =  self.searchBar.searchTextField;
  • 修改UITextFiled的占位符字体大小以及颜色
    通过属性字符串来进行修改替代KVC方式:
UITextField *textField = [[UITextField alloc] init];
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString: textField.placeholder attributes:@{NSForegroundColorAttributeName : [UIColor blackColor],NSFontAttributeName:[UIFont systemFontOfSize:16]}];
textField.attributedPlaceholder = attributedStr;
  • 设置UISearchBar的cancelButton
    iOS13可以通过searcBar的层级遍历subviews获取到,但要注意的是iOS13 UISearchBar的层级有所不同,需要多遍历一层:
for (UIView *v1 in [self.searchBar subviews]) {
    for (UIView *v2 in [v1 subviews]) {
        for (UIView *v3 in [v2 subviews]) {
            if([v3 isKindOfClass:[UIButton class]]){
                UIButton *cancelButton = (UIButton *)v3;
                ...
            }
        }
    }
}
  • 设置状态栏背景颜色
    之前可以通过KVC获得状态栏,再设置其背景颜色;
[[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];

iOS13中的解决方法是使用新APIUIStatusBarManager处理:

UIStatusBarManager *statusBarManager = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager;
if ([statusBarManager respondsToSelector:@selector(createLocalStatusBar)]) {
    UIView *localStatusBar = [statusBarManager performSelector:@selector(createLocalStatusBar)];
    if ([localStatusBar respondsToSelector:@selector(statusBar)]) {
        _statusBar = [localStatusBar performSelector:@selector(statusBar)];
    }
}

通过这种方式获得的状态栏,本质是新建了一个,修改此状态栏背景颜色不影响系统状态栏;所以要想状态栏显示我们想要的颜色,需要将这个创建的状态栏添加至UIWindow上,在界面销毁时再将其移出;

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [[UIApplication sharedApplication].keyWindow addSubview:_statusBar];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [_statusBar removeFromSuperview];
    _statusBar = nil;
}

或者简单点可以直接新建一个和状态栏frame一样的view,添加到window上;

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    _customStatusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame];
    [[UIApplication sharedApplication].keyWindow addSubview:_customStatusBar];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [_customStatusBar removeFromSuperview];
    _customStatusBar = nil;
}

UIStatusBarManager这种方式同样可以获取到状态栏网络状态;
具体可以参考iOS13 获取StatusBar并且获取网络状态

UISearchBar删除UISearchBarBackground崩溃

去除UISearchBar背景色的代码

    for (UIView *view in self.searchBar.subviews.lastObject.subviews) {
        if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
            [view removeFromSuperview];
            break;
        }
    }

以上代码在iOS13中,因为渲染问题而crash;解决方法是将[view removeFromSuperview];更改为view.layer.contents = nil;即可;

模态弹出默认交互方式更改

通过模态presentViewController跳转到另一个界面,iOS13之前modalPresentationStyle默认为UIModalPresentationFullScreen,而在iOS13默认为UIModalPresentationAutomatic;该方式present到UIAlertController等弹框界面效果和UIModalPresentationFullScreen一样;但present到一般vc时不会是全屏的,和之前相比差异明显;
同样的,使用Xcode11及之后版本编译才会有这种差异;反之则不受影响;

UITextView设置editable = NO的问题

设置textView. editable = NO;代码后,iOS13中textView中的文字会显示不全;
解决方法有:

  • 替换为:textView.userInteractionEnabled = NO;
  • 设置textView.textContainerInset = UIEdgeInsetsZero;

MPMoviePlayerController不可使用

使用Xcode11编译,使用MPMoviePlayerController的代码崩溃;报错:

MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.

UITableViewCell上的UILabel点击高亮显示问题

UILabel设置背景颜色为和cell一样的颜色,点击cell高亮显示的时候,iOS13 cell背景颜色变灰色,但仍会看到label背景颜色,体验非常不好(之前版本系统是看不到label背景颜色的);解决方法是将label设置为透明;

CNCopyCurrentNetworkInfo获取不到WiFi SSID

iOS13增加了wifi信息的隐私保护,据说是为了防止开发人员通过WiFi SSID信息推断出用户的位置信息;所以在iOS13中如果用户没有开启定位权限,那么通过CNCopyCurrentNetworkInfo获取的SSID为空;也就是说SSID信息和定位绑定在一起了;
解决方案:把获取SSID当成获取用户位置信息处理就行了;即在获取信息前申请用户定位权限授权,如果用户没有开启该权限根据自己的产品需求是否提示/引导用户开启;

MJExtension字典转模型NSNull处理的不同

将服务端数据字典转换为模型时,如果遇到服务端给的数据为NSNull时,iOS13,mj_JSONObject其中 class_copyPropertyList方法得到的属性里会多了一种EFSQLBinding类型,而且属性数量也不准确;这样会导致崩溃问题;不过MJExtension这个库也随即适配了iOS13,将该库升级到最新的即可;

data类型的description方法返回的字符串不同

iOS13调用description方法返回的字符串会多出length,bytes等字符串;类似:
{length = 32, bytes = 0x778a7995 29f32fb6 74ba8167 b6bddb4e ... b4d6b95f 65ac4587 }
如果之前获取推送的deviceToken字符串是通过description方法获取的,就会有问题了;解决方法:

    - (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])];
      ...
    }
2019-10-21补充

UIImageView设置圆角问题

UIImageView设置圆角,且为设置背景颜色(或背景颜色设置为透明),个别图片圆角会有偏差;

aa

设置背景颜色即可解决问题;

Dark Mode(深色模式)

iOS13支持深色模式:UIKit提供新的系统颜色和 api 来适配不同颜色模式,xcassets 对素材适配也做了调整,具体适配可见: Implementing Dark Mode on iOS;
大部分APP暂时都没有计划适配Dark Mode,不适配Dark Mode的需要注意:

  • UIView未显示的设置背景颜色的(使用系统默认颜色),如果是Dark Mode,那么背景颜色会是黑色,会造成界面显示bug;
  • UITextField的文字Dark Mode模式下默认为白色,同样会有问题;
  • 其他类似的颜色问题;

解决方法是:

  • 需要设置颜色的地方,都需显式的用代码设置(而不是采用系统默认的);但如果这种改动比较多的,工作量太大;
  • info.plist配置APP的显示模式为Light Mode,这样就算手机设置了Dark Mode对APP是不影响的;具体设置如下:
dd

获取不到用户通讯录备注信息

iOS13中禁止开发者访问用户通讯录备注信息,所以在获取通讯录的keys中不能有下面的这个属性
Contacts 的

CNContactNoteKey 

或者
AddressBook的

kABPersonNoteProperty

以上汇总的是目前为止遇到的各种问题,欢迎各位补充

你可能感兴趣的:(iOS13适配(踩坑)不完全汇总)