美文网首页
iOS各版本差异汇总(从8.0开始且不包括UI篇)

iOS各版本差异汇总(从8.0开始且不包括UI篇)

作者: 赵永洪 | 来源:发表于2020-04-15 11:37 被阅读0次

    一.前言介绍

           此文档描述了从iOS8.0到目前的iOS13版本更新需要兼容的地方--- 仅供iOS开发人员参考

    .iOS 8.0

    1.定位功能使用改变

    // 判断定位操作是否被允许if([CLLocationManager locationServicesEnabled]) {    locationManager = [[CLLocationManager alloc] init];    locationManager.delegate = self;    [locationManager startUpdatingLocation];}else {    //提示用户无法进行定位操作}

    如果在iOS8下用这样的方式,你会发现无法定位,那是因为iOS8下添加了新的方法

     /表示使用应用程序期间  开启定位  

    - (void)requestWhenInUseAuthorization  

    //表示始终 开启定位  

    - (void)requestAlwaysAuthorization

    两者区别在于,iOS7 开始,有更强大的后台运行功能,如果 用 requestAlwaysAuthorization 方法,则表示后台运行时也会用到定位

    iOS8 下使用系统定位如下:

    / 判断定位操作是否被允许  

     if([CLLocationManager locationServicesEnabled]) {  

            locationManager = [[CLLocationManager alloc] init];  

            locationManager.delegate = self;  

     //兼容iOS8定位  

            SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");  

     if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&

                [locationManager respondsToSelector:requestSelector]) {  

                [locationManager requestWhenInUseAuthorization];  

    } else {

                [locationManager startUpdatingLocation];  

            }  

     return YES;

        }else {

     //提示用户无法进行定位操作  

        }  

     return NO;

    除了这些,你还需要在 info.plist 里面添加新的键值,否则 也是无法定位的

    2.UIActionSheet and UIAlertView 的升级

    在iOS8里面,官方提供了新的类UIAlertController来替换UIActionSheet and UIAlertView。

    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"My Alert"  message:@"This is an alert."  preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction defaultAction = [UIAlertAction actionWithTitle:@"OK"style:UIAlertActionStyleDefault handler:^(UIAlertAction  action) {}];

    [self presentViewController:alert animated:YES completion:nil];

    3.解决跳转到系统设置里自己App的页面

    在iOS5.0时时可以跳转到系统的设置页的。但是在5.1之后就不可以了。

    刚才研究了下这个问题,发现只有iOS8可以跳转到系统设置里自己App的页面。

    目前没有找到iOS7怎么跳转过去。如果你知道请一定要留言告知,Thanks!

    下面说下iOS8是如何跳转的,以下是代码:

    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];

    if ([[UIApplication sharedApplication] canOpenURL:url]) {

       [[UIApplication sharedApplication] openURL:url];

    }

    .iOS 9.0

    1. 后台定位类app适配点

    在iOS8中,APP的定位服务apple就做了一些修改,需要用户申请相应的权限,并在info.plist文件中添加对应的键值

    在iOS9系统中,定位服务的做法基本没有改变,对于前台的定位没有影响,但app中如果需要后台定位,那么还需要多做一些操作,例如:

    manager = [[CLLocationManager alloc]init];

     //申请后台定位权限

        [manager requestAlwaysAuthorization];

        manager.delegate=self;

     //=======================================

     //下面这个是iOS9中新增的方法 开启后台定位

        manager.allowsBackgroundLocationUpdates = YES;

     //======================================

        [manager startUpdatingLocation];

    通过上面简单的配置直接运行的话,程序会崩溃掉,还需要在plist文件中做一些配置

    2. 安装不受信任的开发者应用

    我们知道,在Xcode7后,开发者可以不用花99dollars去购买开发者账号而可以在自己的iphone上进行测试。在安装这些应用时,iOS9系统不再向以前那样,再安装时提示一个信任的按钮。

    3. BitCode的配置

    BitCode是app的一种中间形式,在iOS9系列专题的前几篇,有对其的简单介绍,举个例子,我们可以在提交app时提交app的bitcode形式,如此一来,apple会对我们的app进行二次优化,在用户下载时根据所需再进行编译打包。在Xocde7中,新建的项目是默认开启BitCode的,如果我们用Xcode7编译提交应用,这里有需要注意适配的地方。

    如果要支持BitCode,需要保证所有的SDK都支持BitCode,如果要更新旧的SDK,只需要在Xcode7上开启BitCode重新制作一遍即可。

    如果不能使所有SDK都支持BitCode,可以在项目中关闭BitCode,在building Setting中搜索BitCode,将enable设置为NO。

    4. URL Scheme白名单

    在iOS9中,apple引入了白名单这个概念,其好处是对app应用内安全进行了加强。在iOS9的适配中,如果我们用到canOpenURL这样的方法,则需要配置白名单。

    首先,我们创建一个测试工程,什么都不用做,只需要添加一个URL Scheme

     |

    在另一个工程中,我们写如下代码:

    BOOL can= [[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"TEST://"]];

        NSLog(@"%d",can);

        [[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"TEST://"]];

    5. iOS9网络适配_ATS:改用更安全的HTTPS

    为了强制增强数据访问安全, iOS9 默认会把 所有的http请求 所有从NSURLConnection 、 CFURL 、 NSURLSession发出的 HTTP 请求,都改为 HTTPS 请求:iOS9.x-SDK编译时,默认会让所有从NSURLConnection 、 CFURL 、 NSURLSession发出的 HTTP 请求统一采用TLS 1.2 协议。因为 AFNetworking 现在的版本底层使用了 NSURLConnection ,众多App将被影响(基于iOS8.x-SDK的App不受影响)。服务器因此需要更新,以解析相关数据。如不更新,可通过在 Info.plist 中声明,倒退回不安全的网络请求。而这一做法,官方文档称为ATS,全称为App Transport Security,是iOS9的一个新特性。

    <key>NSAppTransportSecurity</key>

    <dict>

    <key>NSAllowsArbitraryLoads</key>

    <true/>

    </dict>

    <key>NSAppTransportSecurity</key>

    <dict>

     <key>NSExceptionDomains</key>

     <dict>

     <key>yourserver.com</key>

     <dict>

     <!--Include to allow subdomains-->

     <key>NSIncludesSubdomains</key>

     <true/>

     <!--Include to allow insecure HTTP requests-->

     <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>

     <true/>

     <!--Include to specify minimum TLS version-->

     <key>NSTemporaryExceptionMinimumTLSVersion</key>

     <string>TLSv1.1</string>

     </dict>

     </dict>

    </dict>

    .iOS 10.0

    1. Notification(通知)

    所有相关通知被统一到了UserNotifications.framework框架中

    增加了撤销、更新、中途还可以修改通知的内容

    通知不在是简单的文本了,可以加入视频、图片,自定义通知的展示等等。

    iOS 10相对之前的通知来说更加好用易于管理,并且进行了大规模优化,对于开发者来说是一件好事

    iOS 10开始对于权限问题进行了优化,申请权限就比较简单了(本地与远程通知集成在一个方法中)。

    2. ATS的问题

    iOS 9中默认非HTTS的网络是被禁止的,当然我们也可以把NSAllowsArbitraryLoads设置为YES禁用ATS。不过iOS 10从2017年1月1日起苹果不允许我们通过这个方法跳过ATS,也就是说强制我们用HTTPS,如果不这样的话提交App可能会被拒绝。但是我们可以通过NSExceptionDomains来针对特定的域名开放HTTP可以容易通过审核。

    3. iOS 10 隐私权限设置

    iOS 10 开始对隐私权限更加严格,如果你不设置就会直接崩溃,现在很多遇到崩溃问题了,一般解决办法都是在info.plist文件添加对应的Key-Value就可以了。

     |

    4. iOS 10 UICollectionView 性能优化

    随着开发者对UICollectionView的信赖,项目中用的地方也比较多,但是还是存在一些问题,比如有时会卡顿、加载慢等。所以iOS 10 对UICollectionView进一步的优化。

    UICollectionView cell pre-fetching预加载机制

    UICollectionView and UITableView prefetchDataSource 新增的API

    针对self-sizing cells 的改进

    5. UITextContentType

    在iOS 10 UITextField添加了textContentType枚举,指示文本输入区域所期望的语义意义。

    使用此属性可以给键盘和系统信息,关于用户输入的内容的预期的语义意义。例如,您可以指定一个文本字段,用户填写收到一封电子邮件确认uitextcontenttypeemailaddress。当您提供有关您期望用户在文本输入区域中输入的内容的信息时,系统可以在某些情况下自动选择适当的键盘,并提高键盘修正和主动与其他文本输入机会的整合。

    6. 字体随着手机系统字体而改变

    当我们手机系统字体改变了之后,那我们App的label也会跟着一起变化,这需要我们写很多代码来进一步处理才能实现,但是iOS 10 提供了这样的属性adjustsFontForContentSizeCategory来设置。因为没有真机,具体实际操作还没去实现,如果理解错误帮忙指正。

    UILabel *myLabel = [UILabel new]; /*

        UIFont 的preferredFontForTextStyle: 意思是指定一个样式,并让字体大小符合用户设定的字体大小。

       */

    myLabel.font =[UIFont preferredFontForTextStyle: UIFontTextStyleHeadline]; /*

     Indicates whether the corresponding element should automatically update its font when the device’s UIContentSizeCategory is changed.

     For this property to take effect, the element’s font must be a font vended using +preferredFontForTextStyle: or +preferredFontForTextStyle:compatibleWithTraitCollection: with a valid UIFontTextStyle.

     */

         //是否更新字体的变化

        myLabel.adjustsFontForContentSizeCategory = YES;

    7. 系统版本判断方法失效

    我们之前的系统版本方法如下

    当系统版本到iOS10.0的时候 9.0和10.0比较的话是降序而不是升序,这样会导致iOS10.0是最早的版本,这样后面要走的iOS10的方法可能都不会走而出现问题

    #define IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"9.0"] != NSOrderedAscending)

    #define IOS8_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"8.0"] != NSOrderedAscending)

    #define IOS7_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"7.0"] != NSOrderedAscending)

    #define IOS6_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"6.0"] != NSOrderedAscending)

    下面这样也不行它会永远返回NO,substringToIndex:1在iOS 10 会被检测成 iOS 1了,

    #define isiOS10 ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=10)

    正确的打开方式应该是:

    #define IOS10_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0)

    #define IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0)

    #define IOS8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

    #define IOS7_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

    #define IOS6_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)

    8. Xcode8 debug输出不相关信息

    升级到Xcode8时,我们在debug的时候控制台输出了很长很长的信息,看着比较烦,怎么屏蔽呢?

    需要edit Scheme添加一个键值对就ok了。

     |

     |

    添加 key:​OS_ACTIVITY_MODE​ value:​disable​

    9.App跳转设置

      openUrl:

      openURL: options: completionHandler:

      prefs:root=某项服务

    若要跳转系统设置,需先再URL type中添加一个prefs值,如下图:

     |

    10. 判断版本方法

    【【UIDevice currentDevice】systemVersion】

    11.推送xcode适配开关

    在targets的Capabiliies内Push Notifications选项开关打开

     |

    然后Background Modes打开如下几个选项

     |

    General内导入UserNotifications.framework

     |

    12.Xib文件

    1) 使用Xcode8 打开xib文件是会出现“choose an initial device view”的提示,直接选择蓝色的 choose Device 就可以了。

    2) 如果布局混乱,在xib的右下角更新一下,即 Update Frame。

    13.代码及API

    1) UIView的代理方法可能会出现报错,删除NSError前面的 nullable就行了。

    2) UIStatusBar的方法过期了,如果项目中设置了statusBar,那就像下面这样写:

    - (UIStatusBarStyle)preferredStatusBarStyle { 

     return UIStatusBarStyleDefault;

    }

    .iOS 11.0

    1.XCode9运行访问系统相册崩溃问题

    现象:如图保存图片功能,在XCode9下运行会崩溃

    原因:info.plist新增了权限配置

    解决:info.plist新增一条权限:Privacy - Photo Library Additions Usage Description

    2.无法获取定位信息,第一次打开app也无法弹出定位权限提示框

    iOS11 定位相关的权限做了更改,在iOS11上使用了新的定位权限key

    解决方案:

    如果原来申请的权限是始终允许NSLocationAlwaysUsageDescription,那么需要在保留原来的key的基础上增加NSLocationWhenInUseUsageDescription和NSLocationAlwaysAndWhenInUsageDescription。

    3.无线真机测试

    这应该也是​xcode 9​的一个亮点吧,但是速度真的不是很干恭维的。注意手机和电脑必须在同一个局域网内

    首先使用手机连接xcode之后,打开​window->Devices and Simulator->勾选Show as run destination和Connect via network​,这样就可以无线测试了,以后妈妈再也不用担心忘记带线了

     |

     |

    iOS11UI方面的适配较多,如启动图、tabbar、刘海儿、导航栏、启动图等适配这些UI方面的适配就没有整理了。。。。。。

    .iOS 12.0

    1.代码中判断是否是iPhone X方法

    之前很多人判断手机是否是iPhone X的方法是根据手机尺寸来的.因为需要对刘海做特殊处理.现在这种方法可能不行了.

    可以根据其他的方法,比如StatusBar或者底部安全距离来判断.

    #define rmStatusBarH ([UIApplication sharedApplication].statusBarFrame.size.height)//(44/20)

    #define KIsiPhoneX ((rmStatusBarH == 44.0) ? YES : NO)

    也可以:

    #define isIPhoneXSeries     ([UIScreen instancesRespondToSelector:@selector(currentMode)] ?\

    (\

    CGSizeEqualToSize(CGSizeMake(375, 812),[UIScreen mainScreen].bounds.size)\

     ||\

    CGSizeEqualToSize(CGSizeMake(414, 896),[UIScreen mainScreen].bounds.size)\

    )\

    :\

    NO)

    2.升级Xcode10后项目报错

    项目中如果使用Cocoapods引用了第三方的库,有可能会升级之后导致编译失败.

    由于我项目中没有使用cocoapods,所以没有遇到,网上查了一下资料,大概是因为:

    iOS 12移除了libstdc++, 用libc++替代:

    多个 info.plist 会引起崩溃.

    可以将多余的info.plist删除

    建议方案:

    Xcode->File->Project Settings-> Build System -> Legacy Build System.

    3.Multiple commands produce 'xxx/Info.plist'

    升级​Xcode 10​之后,编译之前的项目,发生编译错误:​Multiple commands produce 'xxx/Info.plist'​,项目中存在重复命名的info.plist文件。

    解决方案:

    (I)标准方案:删除所有重复命名的文件。

    (II)临时方案:

    ​xcworkspace​项目:Xcode菜单栏​File​ -> ​Workspace Settings​ -> ​Build System​ -> ​Legacy Build System​;

    ​xcodeprj​项目:Xcode菜单栏​File​ -> ​Project Settings​ -> ​Build System​ -> ​Legacy Build System​。

    4.​iOS 12​系统​WiFi​获取​SSID​(wifi名称)和​BSSID​(mac地址)失败

    在​iOS 12​系统之后,苹果提升了获取​WiFi​名称和​mac​地址的权限控制,要获取这些信息,需要手动为应用打开获取WiFi信息的权限。

    解决方案:

    在开发者账号中,勾选项目的​App ID​的​Access WiFi Infomation​选项;

    在Xcode的​Capabilities​中,勾选项目的​Access WiFi Infomation​选项。

    5.​Xcode 10​中​#import​的时候闪退或导入头文件不提示

    在​Xcode 10​中出现输入​#import​引入文件/类库头文件的时候​Xcode​闪退。或者输入​#import​导入头文件时不提示。

    解决方案:

    ​xcworkspace​项目:Xcode菜单栏​File​ -> ​Workspace Settings​ -> ​Build System​ -> ​Legacy Build System​;

    ​xcodeprj​项目:Xcode菜单栏​File​ -> ​Project Settings​ -> ​Build System​ -> ​Legacy Build System​。

    6.​webView​播放视频返回后状态栏消失

    视频播放完成主​window​成为​KeyWindow​的时候仍隐藏着​UIStatusBar​。

    解决方案:

    - (void)videoPlayerFinishedToShowStatusBar

    {

     if (@available(iOS 12.0, *)) {

            [[NSNotificationCenter defaultCenter] addObserverForName:UIWindowDidBecomeKeyNotification

     object:self.window

                                                             queue:[NSOperationQueue mainQueue]

                                                        usingBlock:^(NSNotification * _Nonnull note) {

                                                            [[UIApplication sharedApplication] setStatusBarHidden:NO

                                                                                                    withAnimation:UIStatusBarAnimationNone];

                                                        }];

        }

    }

    7.Xcode 10  imageNamed: 不能正常加载Assets里面的图片

    imageNamed:加载Assets中的图片出来是nil,将图片放到bundle中即可。

    .iOS 13.0

    1.私有KVC

    iOS不允许​valueForKey​、​setValue: forKey​获取和设置私有属性,需要使用其它方式修改

    如:

    [textField setValue:[UIColor red] forKeyPath:@"_placeholderLabel.textColor"];

    //替换为

    textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"输入"attributes:@{NSForegroundColorAttributeName: [UIColor red]}];

    2.黑线处理crash

    之前为了处理搜索框的黑线问题会遍历后删除​UISearchBarBackground​,在iOS13会导致UI渲染失败crash;解决办法是设置​UISearchBarBackground​的layer.contents为nil

    public func clearBlackLine() {

     for view in self.subviews.last!.subviews {

     if view.isKind(of: NSClassFromString("UISearchBarBackground")!) {

                    view.backgroundColor = UIColor.white

    view.layer.contents = nil

     break

                }

            }

        }

    3.模态跳转(modal present)

    iOS13模态跳转出来的界面,不再像之前版本是全屏的了

    如果将此属性设置为​UIModalPresentationAutomatic​,则读取该属性将始终返回具体的呈现样式。 默认情况下,​UIViewController​将​UIModalPresentationAutomatic​解析为​UIModalPresentationPageSheet​,但是系统提供的子类可以将​UIModalPresentationAutomatic​解析为其他具体的呈现样式。 保留​UIModalPresentationAutomatic​的分辨率供系统提供的视图控制器使用。从iOS 13.0开始,在iOS上默认为​UIModalPresentationAutomatic​,在以前的版本上默认为​UIModalPresentationFullScreen​。 在所有其他平台上,默认为​UIModalPresentationFullScreen​。

    ​UIModalPresentationPageSheet​就是下面的样子

     |

    知道了原因,我们做适配也简单了,就是设置下属性的事:

    let second = SecondViewController()

    second.modalPresentationStyle = .fullScreen

    present(second, animated: true, completion: nil)

    4.暗黑模式

    iOS13使用暗黑模式时,UIView默认背景色会变成暗黑色。适配暗黑模式的工作量较大,改为强制使用正常模式。

    处理方案:在plist文件中增加配置项UIUserInterfaceStyle,值为Light。

    5.蓝牙权限更新

    上传App Store时,如果引用了CoreBluetooth.framework,则需要添加描述配置​NSBluetoothAlwaysUsageDescription​,否则无法提交。旧版本的个推SDK引入时依赖CoreBluetooth,后续版本已修改不再依赖CoreBluetooth。

    处理方案:检查其他第三方库并未依赖CoreBluetooth.framework,删除对该库的引用。

    6.废弃UIWebview改为WKWebView

    暂时没有强制修改,但是已经发邮件提示,需要做一下修改,否则可能无法上架哈

    7.KVC限制

    在iOS13上通过KVC来修改系统API私有属性时会报错

    *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Access to xxx's _xxx ivar is prohibited. This is an application bug'

    处理方案:

    1、全局搜索KVC的使用方法,未发现使用KVC方式修改私有属性的代码

    2、平时开发时注意KVC的使用

    8. 第三方登录支持苹果登录(Sign In with Apple)

    苹果更新了审核指南,要求所有专门使用第三方登录的App,2020 年 4 月之前,都必须接入 Sign in with Apple。符合以下条件的App,可以不接入:

    使用自建账户和登录系统;

    要求用户使用现有的教育或企业账户登录的教育、企业或商业类应用;

    使用政府或行业支持的公民身份识别系统或电子 ID 来验证用户;

    应用特定于第三方服务,用户需要使用邮箱、社交媒体或其它第三方账户才能访问其内容的应用;

    9.使用MJExtension 中处理NSNull的不同

    这个直接会导致Crash的在将服务端数据字典转换为模型时,如果遇到服务端给的数据为NSNull时,

    mj_JSONObject,其中 class_copyPropertyList方法得到的属性里,多了一种EFSQLBinding类型的东西,而且属性数量也不准确,

    那就没办法了,

    我只能改写这个方法了,这个组件没有更新的情况下,写了一个方法swizzling掉把当遇到 NSNull时,直接转为nil了。

    10.WKWebView 中测量页面内容高度的方式变更

    iOS 13以前

    document.body.scrollHeight

    iOS 13中

    document.documentElement.scrollHeight

    两者相差55 应该是浏览器定义高度变了

    11. 友盟消息推送,获取deviceToken适配

    - (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{if(![deviceToken isKindOfClass:[NSData class]])return;      const unsigned *tokenBytes = (constunsigned *)[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])];      pushDeviceToken = hexToken;      NSLog(@"deviceToken:%@",hexToken);}

    12.获取Wi-Fi名

    iOS12之前

    id info = nil;

        NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();

     for (NSString *ifnam in ifs) {

            info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);

            NSString *str = info[@"SSID"];//name

        }

    iOS 12之后以上方法获取不到,需要在Xcode中TARGET-->Capabilities打开Access WiFi Information选项

     |

    iOS 13之后以上方法获取Wi-Fi名返回的都是固定值"WLAN",这里可能是因为苹果保护用户隐私而产生的问题,因为通过wifi信息可以定位到用户地理位置。所以iOS13以后如果想要继续获取WiFi名称,需要在调用接口前判断用户是否同意App使用地理位置信息。可以在程序一启动时请求用户权限,调用的方法如下:

    #import <CoreLocation/CoreLocation.h>

    @property (strong, nonatomic) CLLocationManager *locationManager;

    NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];

    CGFloat version = [phoneVersion floatValue];

    // 如果是iOS13 未开启地理位置权限 需要提示一下

    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined && version >= 13) {

     self.locationManager = [[CLLocationManager alloc] init];

        [self.locationManager requestWhenInUseAuthorization];

    }

    如果用户拒绝了授权,在需要获取Wi-Fi名的界面加上提示:

        NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];

        CGFloat version = [phoneVersion floatValue];

        //如果开启地理位置权限未开启 需要提示一下

     if (([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined ||[CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted ||[CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied  )&& version >= 13) {

    [PracticalTools showAlertViewWithTitle:@"提示" message:@"您的位置权限尚未授权,将无法获取当前Wi-Fi进行配置网络,请前往“设置”-“****App”-“位置”进行授权!" doneText:@"确定" cancelText:nildoneHandle:nil cancelHandle:nil vc:self];

        }

    13.iOS13 正确的获得Devicetoken

    #include <arpa/inet.h>

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

    {

     if (![deviceToken isKindOfClass:[NSData class]]) return;

     const unsigned *tokenBytes = (const unsigned *)[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])];

        NSLog(@"deviceToken:%@",hexToken);

    }

    14.Xcode 11 创建的工程在低版本设备上运行黑屏

    使用 Xcode 11 创建的工程,运行设备选择 iOS 13.0 以下的设备,运行应用时会出现黑屏。这是因为 Xcode 11 默认是会创建通过 UIScene 管理多个 UIWindow 的应用,工程中除了 AppDelegate 外会多一个 SceneDelegate.

     |

    这是为了 iPadOS 的多进程准备的,也就是说 UIWindow 不再是 UIApplication 中管理。但是旧版本根本没有 UIScene,因此解决方案就是在 AppDelegate 的头文件加上:

    @property (strong, nonatomic) UIWindow *window;

    15.NSAttributedString优化

    对于UILabel、UITextField、UITextView,在设置NSAttributedString时也要考虑适配Dark Mode,否则在切换模式时会与背景色融合,造成不好的体验

    不建议的做法

    NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16]};

    NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案"attributes:dic];

    推荐的做法

    // 添加一个NSForegroundColorAttributeName属性

    NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor labelColor]};

    NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案"attributes:dic];

    相关文章

      网友评论

          本文标题:iOS各版本差异汇总(从8.0开始且不包括UI篇)

          本文链接:https://www.haomeiwen.com/subject/rhaqvhtx.html