暗黑模式是iOS13的重要更新之一,随之而来的是我们能从系统设置中“显示与亮度”中选择“浅色”、“深色”两种模式,并且可以设置自动切换,“控制中心”亮度调节中也可直接调节。UIKit
提供新的系统颜色和 api 来适配不同颜色模式,xcassets
对素材适配也做了调整,具体适配可见: Implementing Dark Mode on iOS
如果不想适配深色模式,可以这样设置
plist
文件中设置UIUserInterfaceStyle
UIUserInterfaceStyleLight
if (@available(iOS 13.0, *)) {
[self setOverrideUserInterfaceStyle:UIUserInterfaceStyleLight];
} else {
// Fallback on earlier versions
}
在 iOS 13 中不再允许使用 valueForKey
、setValue:forKey:
等方法获取或设置私有属性,虽然编译可以通过,但是在运行时会直接崩溃
// 使用的私有方法
[textField setValue:UIColor_d2 forKeyPath:@"_placeholderLabel.textColor"];
textField.placeholder = placeholderStr;
崩溃信息:
// 崩溃提示信息
*** Terminating app due to uncaught exception ‘NSGenericException’, reason: ‘Access to UITextField’s _placeholderLabel ivar is prohibited. This is an application bug’
解决方案:
NSMutableAttributedString *placeholderString = [[NSMutableAttributedString alloc] initWithString:placeholderStr
attributes:@{NSForegroundColorAttributeName:UIColor_d2}];
textField.attributedPlaceholder = placeholderString;
原本可以直接将 NSData
类型的 deviceToken
转换成 NSString
字符串,然后替换掉多余的符号即可:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"deviceToken:%@", token);
}
在 iOS 13 中,这种方法已经失效,NSData
类型的 deviceToken
转换成的字符串变成了:
{length=32,bytes=0xd02daa63aade35488d1e24206f44037d…fd6b2fac80bddd2d}
需要进行一次数据格式处理,参考友盟的做法,可以适配新旧系统,获取方式如下:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
if (![deviceToken isKindOfClass:[NSData class]]) return;
const unsigned *tokenBytes = [deviceToken bytes];
NSString *token = [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:%@", token);
}
这样就获取到正确的 deviceToken
字符串
d02daa63aade35488d1e24206f44037dce9ece7f85adf6acfd6b2fac80bddd2d
在 iOS 13 UIModalPresentationStyle
枚举的定义中,苹果新加了一个枚举值:
typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
...
UIModalPresentationAutomatic API_AVAILABLE(ios(13.0)) = -2,
};
在 iOS 13 中此枚举值直接成为了模态弹出的默认值,因此 presentViewController
方式打开视图是下滑返回的视差效果。如果你完全接受苹果的这个默认效果,那就不需要去修改任何代码。如果你原来就比较细心,已经设置了modalPresentationStyle
的值,那你也不会有这个影响。对于想要找回原来默认交互的同学,直接设置如下即可:
self.modalPresentationStyle = UIModalPresentationOverFullScreen;
在 iOS 9 之前播放视频可以使用 MediaPlayer.framework
中的MPMoviePlayerController
类来完成,它支持本地视频和网络视频播放。但是在 iOS 9 开始被弃用,如果在 iOS 13 中继续使用的话会直接抛出异常:
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.’
解决方案是使用 AVFoundation
里的 AVPlayer
。
最近一次提审被拒情况,被拒原因之一就是需要添加蓝牙权限获取描述,提交以后构建显示正在处理中,等几分钟会自动消失,构建不成功,Apple发送邮件提示:
ITMS-90683: Missing Purpose String in Info.plist - Your app’s code references one or more APIs that access sensitive user data. The app’s Info.plist file should contain a
NSBluetoothAlwaysUsageDescription
key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting Spring 2019, all apps submitted to the App Store that access user data are required to include a purpose string. If you’re using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn’t contain the APIs. Learn more (https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy).
原因是iOS13 将废弃 NSBluetoothPeripheralUsageDescription
替换为NSBluetoothAlwaysUsageDescription
解决方法,在 info.plist
中添加新字段
NSBluetoothAlwaysUsageDescription
App需要您的同意,才能访问蓝牙
重新上传即可