通过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设置圆角,且为设置背景颜色(或背景颜色设置为透明),个别图片圆角会有偏差;
设置背景颜色即可解决问题;
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是不影响的;具体设置如下:
获取不到用户通讯录备注信息
iOS13中禁止开发者访问用户通讯录备注信息,所以在获取通讯录的keys中不能有下面的这个属性
Contacts 的
CNContactNoteKey
或者
AddressBook的
kABPersonNoteProperty