iOS 10 适配

随着 iOS 10的发布,大家的App都需要适配 iOS 10,下面我总结了一些关于iOS 10的适配方面的问题。

1. 隐私数据的访问问题:

你的项目中访问了隐私数据,比如:相册,相机,联系人等,在xcode 8 中打开编译的话,统统回crash,控制台输出日志如下

This app has crashed because it attempted to access privacy-sensitive data without a usage description.The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app use this data.

这是因为iOS对用户的安全和隐私的增强,在申请很多私有权限的时候都需要添加描述,但是,在使用Xcode 8之前的Xcode还是使用系统的权限通知框.
要想解决这个问题,只需要在info.plist添加NSContactsUsageDescription的key, value自己随意填写就可以,这里列举出对应的key(Source Code模式下):

<!-- 相册 --> 
<key>NSPhotoLibraryUsageDescription</key> 
<string>App需要您的同意,才能访问相册</string> 
<!-- 相机 --> 
<key>NSCameraUsageDescription</key> 
<string>App需要您的同意,才能访问相机</string> 
<!-- 麦克风 --> 
<key>NSMicrophoneUsageDescription</key> 
<string>App需要您的同意,才能访问麦克风</string> 
<!-- 位置 --> 
<key>NSLocationUsageDescription</key> 
<string>App需要您的同意,才能访问位置</string> 
<!-- 在使用期间访问位置 --> 
<key>NSLocationWhenInUseUsageDescription</key> 
<string>App需要您的同意,才能在使用期间访问位置</string> 
<!-- 始终访问位置 --> 
<key>NSLocationAlwaysUsageDescription</key> 
<string>App需要您的同意,才能始终访问位置</string> 
<!-- 日历 --> 
<key>NSCalendarsUsageDescription</key> 
<string>App需要您的同意,才能访问日历</string> 
<!-- 提醒事项 --> 
<key>NSRemindersUsageDescription</key> 
<string>App需要您的同意,才能访问提醒事项</string> 
<!-- 运动与健身 --> 
<key>NSMotionUsageDescription</key> <string>App需要您的同意,才能访问运动与健身</string> 
<!-- 健康更新 --> 
<key>NSHealthUpdateUsageDescription</key> 
<string>App需要您的同意,才能访问健康更新 </string> 
<!-- 健康分享 --> 
<key>NSHealthShareUsageDescription</key> 
<string>App需要您的同意,才能访问健康分享</string> 
<!-- 蓝牙 --> 
<key>NSBluetoothPeripheralUsageDescription</key> 
<string>App需要您的同意,才能访问蓝牙</string> 
<!-- 媒体资料库 --> 
<key>NSAppleMusicUsageDescription</key> 
<string>App需要您的同意,才能访问媒体资料库</string>

如果不起作用,可以请求后台权限,类似于这样

<key>UIBackgroundModes</key>
<array> 
<!-- 在这里写上你在后台模式下要使用权限对应的key --> 
<string>location</string>
...
</array>

或者在Xcode里选中当前的target,选择Capabilities,找到Background Modes,打开它,在里面选择对应权限
two

2.Xcode8更新xib版本后遇到的frame问题和解决办法

问题:更新xcode8后打开xib都会提示是否更新
xib版本

更新版本后,以前在 awakeFromNib 方法里获取某个 UIView 的fame可能会失效,比如说

- (void)awakeFromNib {
[super awakeFromNib];
CGFloat raduis = _headImg.frame.size.height/2;
_headImg.layer.cornerRadius = raduis;
_headImg.layer.masksToBounds = YES;
}

这段设置圆角的代码看上去没任何问题,但是运行后会发现 _headImg 不见了,找了半天之后打断点后发现 _headImg 的bounds竟然是(0, 0, 1000, 1000)

在SO上查了一下,如果不是Xcode8的bug的话,应该就是苹果修改了xib的layout cycle导致的问题

参考链接

http://stackoverflow.com/questions/39380128/ios-10-gm-with-xcode-8-gm-causes-views-to-disappear-due-to-roundedcorners-clip

http://stackoverflow.com/questions/39136637/clipstobounds-causes-uiimage-to-not-display-in-ios10-xcode-8

解决办法

如果是一小部分地方受影响的话,那么只需要简单的在获取某个 UIView 的frame前加入一句 [self layoutIfNeeded] 就可以了,但是工程里影响到的类比较多,改动起来比较麻烦话,可以通过hook awakeFromNib 的方法进行解决

@implementation NSObject (adaptXocde8)
+(void)load
{
Method originalMethod = class_getInstanceMethod([NSObject class], @selector(awakeFromNib));
Method swapMethod = class_getInstanceMethod([NSObject class], @selector(awakeFromNibNew));
method_exchangeImplementations(originalMethod, swapMethod);

}

- (void)awakeFromNibNew
{
if([self respondsToSelector:@selector(layoutIfNeeded)])
{
    [self performSelector:@selector(layoutIfNeeded) withObject:nil];
}
[self awakeFromNibNew];
}
@end

3. 未完待续

坚持原创技术分享,您的支持将鼓励我继续创作!