to
- automaticallyAdjustsScrollViewInsets
在iOS 11中,苹果废弃了
- contentInsetAdjustmentBehavior
的
- UIViewController
属性,改用
- automaticallyAdjustsScrollViewInsets
的
- UIScrollView
属性来替换它。
- contentInsetAdjustmentBehavior
- // OC
- @property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets API_DEPRECATED_WITH_REPLACEMENT("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0, 11.0), tvos(7.0, 11.0)); // Defaults to YES
- //swift
- @available(iOS, introduced: 7.0, deprecated: 11.0) open
- var automaticallyAdjustsScrollViewInsets: Bool // Defaults to YES
如果你的工程中没有添加
对应的启动图,你会发现顶部和底部的一部分都是黑色的,那部分就是安全域。 想要对
- iPhone X
做屏幕适配,第一步先要添加启动图。
- iPhone X
自动计算高度
- UITableView
在iOS 11中,
的
- UITableView
、
- estimatedRowHeight
、
- estimatedSectionHeaderHeight
默认都是开启的。真是令人惊喜。
- estimatedSectionFooterHeight
- @property (nonatomic) CGFloat rowHeight; // default is UITableViewAutomaticDimension
- @property (nonatomic) CGFloat sectionHeaderHeight; // default is UITableViewAutomaticDimension
- @property (nonatomic) CGFloat sectionFooterHeight; // default is UITableViewAutomaticDimension
- @property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
- @property (nonatomic) CGFloat estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
- @property (nonatomic) CGFloat estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
在我们的app中,首页的
列表是手动计算的行高,突然出现了以往只有开启自动计算行高才会出现的滚动条跳动的现象,给
- UITableView
的
- TableView
加了
- contentSize
,果然一直在变。然后在这里找到了原因。
- observer
在使用
的时候,本身代码存在一个
- MJRefersh
,原来并没有发现,iOS 11 帮我发现了这个问题。
- bug
- // tableView 设置
- let footer = MJRefreshAutoFooter(refreshingBlock: { [weak self] in
- if let strongSelf = self {
- if let block = strongSelf.footerBlock {
- block()
- }
- }
- })
- footer?.triggerAutomaticallyRefreshPercent = -20
- tableView.mj_footer = footer
- // 请求结束后处理(错误)
- models.append(requestModels)
- if models.count < pageSize { // 这里是个bug
- tableView.mj_footer.endRefreshingWithNoMoreData()
- } else {
- tableView.mj_footer.state = .idle
- }
- tableView.reloadData()
- // 请求结束后处理(正确)
- if requestModels.count < pageSize { // 修复bug
- tableView.mj_footer.endRefreshingWithNoMoreData()
- } else {
- tableView.mj_footer.state = .idle
- }
- models.append(requestModels)
- tableView.reloadData()
上面代码中,在
之前也存在隐含的问题,就是
- iOS 11
一直不能被标记为
- tableView footer
的状态,即使没有数据了,用户下拉依然后发起请求。 在
- 无更多数据
中,由于估算行高,互动到底部时,依然会触发
- iOS 11
的
- tableView
和
- contentSize
变化,同时会触发
- contentOffset
, 和
- refreshingBlock
的
- tableView
,导致了最后一页数据陷入了循环请求。
- reloadData
引申问题 如果存在使用监听
的
- tableView
和
- contentSize
变化来触发的一些事件,最好把
- contentOffset
的自动计算行高关掉,以免出现问题。
- tableView
众所周知,iPhone X多了个“美美的”刘海,它的状态栏发生了变化。这也导致了原来从状态栏视图获取网络状态的API出了问题,会导致闪退。
- // 获取当前app状态栏子视图
- UIApplication * app = [UIApplication sharedApplication];
- NSArray * children = [[[app valueForKeyPath: @"statusBar"] valueForKeyPath: @"foregroundView"] subviews];
- int type = 0;
- for (id child in children) {
- if ([child isKindOfClass: NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
- type = [[child valueForKeyPath: @"dataNetworkType"] intValue];
- }
- }
- switch (type) {
- case 1:
- return@"2G";
- case 2:
- return@"3G";
- case 3:
- return@"4G";
- case 5:
- return@"WIFI";
- default:
- return@"Unknow";
- break;
- }
不过你依然可以用
类似的方式,获取网络状态:
- AFNetworking
- SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
- SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
- SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
- switch (self.networkReachabilityAssociation) {
- case AFNetworkReachabilityForName:
- break;
- case AFNetworkReachabilityForAddress:
- case AFNetworkReachabilityForAddressPair:
- default: {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
- SCNetworkReachabilityFlags flags;
- SCNetworkReachabilityGetFlags(self.networkReachability, &flags);
- AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
- dispatch_async(dispatch_get_main_queue(), ^{
- callback(status);
- NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
- [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }];
- });
- });
- }
- break;
- }
- static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) {
- BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
- BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
- BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0));
- BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0);
- BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction));
- AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown;
- if (isNetworkReachable == NO) {
- status = AFNetworkReachabilityStatusNotReachable;
- }
- #if TARGET_OS_IPHONE
- else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
- status = AFNetworkReachabilityStatusReachableViaWWAN;
- }
- #endif
- else {
- status = AFNetworkReachabilityStatusReachableViaWiFi;
- }
- return status;
- }
- // 原有
- #define MPStatusBarHeight (20)
- // 新的
- #define MPStatusBarHeight (UIApplication.sharedApplication.statusBarFrame.size.height)
- /* 坑在此处 */
- // application 的 statusBarFrame 在隐藏状态栏的时候是 CGRectZero
- @property(nonatomic,readonly) CGRect statusBarFrame __TVOS_PROHIBITED; // returns CGRectZero if the status bar is hidden
友盟分享 SDK 6.4.6 版本提供的界面没有适配
需要更新
- iPhone X
到最新的 6.8.0 版本,很遗憾的是,目前最新的友盟所有产品都没有提供
- SDK
版本,需要手动集成。 在集成过程中遇到一个坑: 由于我们工程同时使用
- cocoapods
引用了友盟分享和友盟统计,本来只想升级友盟分享,于是直接跳到集成友盟分享的文档部分,执行了下面的操作:
- pod
- 、移除pod对 UMShare的引用,执行 pod install
- 、添加UMShareSDK到工程
- 、修改文件引用错误
- 、清除DerivedData
- 、在模拟器build
报错:
询问了友盟客服(马上就回复了,很给力),是由于没有集成
基础库,回过头来看文档,发现集成友盟任意库都需要加入
- common
基础库。 但是一旦加入
- common
基础库,又会和使用
- common
引用的友盟统计冲突,无奈,只能统计库和分享库都换成手动引用。
- pod
- UIToolBar
在
中两侧添加了
- UIToolBar
,在
- UIBarButtonItem
之前会布局在边,在
- iOS 11
中两个item是紧挨着的,需要在中间添加
- iOS 11
类型的
- UIBarButtonSystemItemFlexibleSpace
才可以。
- item
保存图片闪退
- ALAssetsLibrary
在 iOS 11 之前,你可以直接使用下面代码来保存图片到相册:
- #import <AssetsLibrary/AssetsLibrary.h>
- // ALAssetsLibrary
- [[[ALAssetsLibrary alloc] init] writeImageDataToSavedPhotosAlbum:imageData metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) {
- [self saveResultWithResult:(error == nil)];
- }];
在 iOS 11中则会直接崩溃,保存图片的新姿势:
参数 | key | Xcode name | 版本 | 说明 |
---|---|---|---|---|
NSPhotoLibraryAddUsageDescription | "Privacy - Photo Library Additions Usage Description" | Specifies the reason for your app to get write-only access to the user’s photo library. SeeNSPhotoLibraryAddUsageDescriptionfor details. | iOS 11 and later | 本参数iOS 11必须追加 |
NSPhotoLibraryUsageDescription | “Privacy - Photo Library Usage Description” | Specifies the reason for your app to access the user’s photo library. SeeNSPhotoLibraryUsageDescriptionfor details. | iOS 6.0 and later | 本参数iOS 10以后必须追加 |
在infoPlist中直接添加(xcode 中 open as Source Code):
- <key>NSPhotoLibraryUsageDescription</key>
- <string>此 App 需要您的同意才能读取媒体资料库</string>
- <key>NSPhotoLibraryAddUsageDescription</key>
- <string>此 App 需要您的同意才能写入媒体资料库</string>
写入直接崩溃,而
- ALAssetsLibrary
保存图片会直接触发向用户请求相册写入权限的 Alert 提示。
- PHPhotoLibrary
- #import <Photos/Photos.h>
- // PHPhotoLibrary
- - (void)saveImageByPHPhotoLibrary:(UIImage *)image {
- [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
- [PHAssetCreationRequest creationRequestForAssetFromImage:image];
- } completionHandler:^(BOOL success, NSError * _Nullable error) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [self saveResultWithResult:(success && error == nil)];
- });
- }];
- }
更新
由于在应用中使用了
,
- WKwebView
在没有处理的情况下,长按图片会弹出保存图片的选项,选择保存图片同样会崩溃。所以该方案不能处理好所有入口,推荐使用方案1。
- WKWebView
在iOS 11系统中,你会发现你原本的一些输入框唤起系统键盘后出现如下的状况:
键盘右上角的
来源: https://juejin.im/post/5a211234f265da430e4ef5ac