人家一步一个脚印,咱是一步一个坑
此次更新Xcode11之后,有需要适配iOS 13的点却没有做的话,出包之后在iOS 13的设备上会crash。Xcode10不用担心,不更新就没问题嘛。
1. UIStatusBarManager
iOS 13 的暗黑模式系统最大限度的接管了状态栏的权限。应用中有获取或修改 UIStatusBar 的操作,在iOS 13都必须重新适配 ,否则都会有这个报错。
'App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.'
UIStatusBarManager.h 文件
#if (defined(USE_UIKIT_PUBLIC_HEADERS) && USE_UIKIT_PUBLIC_HEADERS) || !__has_include(<UIKitCore/UIStatusBarManager.h>)
//
// UIStatusBarManager.h
// UIKit
//
// Copyright © 2018 Apple Inc. All rights reserved.
//
#import <UIKit/UIWindowScene.h>
NS_ASSUME_NONNULL_BEGIN
UIKIT_EXTERN API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos)
@interface UIStatusBarManager : NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@property (nonatomic, readonly) UIStatusBarStyle statusBarStyle;
@property (nonatomic, readonly, getter=isStatusBarHidden) BOOL statusBarHidden;
@property (nonatomic, readonly) CGRect statusBarFrame; // returns CGRectZero if the status bar is hidden
@end
@interface UIWindowScene (StatusBarManager)
@property (nonatomic, readonly, nullable) UIStatusBarManager *statusBarManager API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos);
@end
NS_ASSUME_NONNULL_END
#else
#import <UIKitCore/UIStatusBarManager.h>
#endif
通过了解之后发现UIWindowScene ,可以通过获取当前window的status去获取状态栏的 statusBarStyle
,statusBarHidden
,statusBarFrame
。
就直接贴上代码
获取状态栏高度
CGFloat statusBarHeight;
if (@available(iOS 13.0, *)) {
statusBarHeight = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame.size.height;
} else {
statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
}
2. UITabBarItem
tabBar
新的设置方法, 需要的话直接到文件里查看就行。
UITabBarAppearance.h
具体不多说。
我踩的属于老坑,之前没出现的问题。下面的写法在iOS13之后,tabbar的未选中状态下的title会不显示,之后发现是设置字体颜色引起的问题
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:normalColor, NSFontAttributeName:[UIFont systemFontOfSize:10]} forState:UIControlStateNormal];
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:selectedColor, NSFontAttributeName:[UIFont systemFontOfSize:10]} forState:UIControlStateSelected];
实则配置 选中/未选中
的title颜色适配 iOS10 后UITabBar 的一个属性即可unselectedItemTintColor
if (@available(iOS 10, *)) {
//选中item颜色
[UITabBar appearance].tintColor = selectedColor;
//未选中颜色
[UITabBar appearance].unselectedItemTintColor = normalColor;
}
else {
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:normalColor} forState:UIControlStateNormal];
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:selectedColor} forState:UIControlStateSelected];
}
之后TabBarItem的状态显示才恢复正常。
3. UISearchBar
iOS 13里KVC是禁止了,不能像以前一样愉快的使用类似方法去设置searchBar的私有属性了。
UITextField *searchTextField = [self valueForKey:@"_searchField"];
[searchField setValue:textColor forKeyPath:@"_placeholderLabel.textColor"];
但是 iOS 13开放了 searchBar
的textFild
但是 iOS 13开放了 searchBar
的textFild
但是 iOS 13开放了 searchBar
的textFild
@interface UISearchBar (UITokenSearch)
@property (nonatomic, readonly) UISearchTextField *searchTextField;
@end
可以放心大胆的使用了。 设置UISearchBar 的 placeholder
if (@available(iOS 13, *)) {
NSAttributedString *attributPlaceholder = [[NSAttributedString alloc] initWithString:placeholder attributes:@{NSForegroundColorAttributeName : textColor, NSFontAttributeName : [UIFont systemFontOfSize:14]}];
self.searchTextField.attributedPlaceholder = attributPlaceholder;
}
else {
UITextField *searchField = [self valueForKey:@"searchField"];
[searchField setValue:textColor forKeyPath:@"_placeholderLabel.textColor"];
}
最后说一句, 做事要细心,用心,专心。
再次感谢 iOS 13 适配 (填坑…)
以上几个更新都必须适配否则会Crash!!!
以上几个更新都必须适配否则会Crash!!!
以上几个更新都必须适配否则会Crash!!!
下面更一些自己遇到的iOS 13下需要兼容的东西
iOS 13中注册推送的 deviceToken 改变,拿不到对应的字符串,而是拿到一个NSData
类型的值
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
做出以下兼容
if (@available(iOS 13, *)) {
const char *bytes = deviceToken.bytes;
NSInteger count = deviceToken.length;
NSMutableString *mutableStr = [NSMutableString string];
for (int i = 0; i < count; i++) {
[mutableStr appendFormat:@"%02x", bytes[i]&0x000000FF];
}
newDeviceToken = mutableStr.copy;
}
else {
newDeviceToken = deviceToken;
}