美文网首页
历代iOS版本 — iOS9

历代iOS版本 — iOS9

作者: Trigger_o | 来源:发表于2020-07-13 12:01 被阅读0次

    一. SDK

    1. 限制HTTP协议,全部改用更安全的HTTPS

    iOS9让所有的HTTP默认使用了HTTPS,原来的HTTP协议传输都改成TLS1.2协议进行传输。直接造成的情况就是App发请求的时候弹出网络无法连接。

    对于这个问题的解决方案,网上有一篇博客已经总结的很好了,我在这就简要的说明怎么处理这种问题.

    HTTPS和HTTP的区别在于哪里呢?

    举个简单的栗子:原来的 HTTP 是塑料水管,容易被戳破;那么如今新设计的 HTTPS 就像是在原有的塑料水管之外,

    再包一层金属水管。一来,原有的塑料水管照样运行;二来,用金属加固了之后,不容易被戳破。

    Apple让你的HTTP采用SSL/TLS协议,就是让你从HTTP转到HTTPS.

    不使用SSL/TLS的HTTP通信,就是不加密的通信!

    所有信息明文传播,带来了三大风险:

    窃听风险(eavesdropping):第三方可以获知通信内容。

    篡改风险(tampering):第三方可以修改通信内容。

    冒充风险(pretending):第三方可以冒充他人身份参与通信。

    SSL/TLS协议是为了解决这三大风险而设计的:

    所有信息都是加密传播,第三方无法窃听。

    具有校验机制,一旦被篡改,通信双方会立刻发现。

    配备身份证书,防止身份被冒充。

    • 在 Info.plist 中声明,倒退回不安全的网络请求依然能让App访问指定http,甚至任意的http(苹果不建议这么做):
    image.png

    需要添加的节点

    http://blog.csdn.net/aa2397199142/article/details/48915377
    参考 :http://www.cnblogs.com/endtel/p/4810042.html

    NSAppTransportSecurity - NSAllowsArbitraryLoads

    这个子节点的意思是:是否仍然允许加载

    设为YES的话就将禁用了AppTransportSecurity转而使用用户自定义的设置,这个问题就解决了。

    2. Bitcode

    bitcode 是被编译程序的一种中间形式的代码。包含 bitcode 配置的程序将会在 App Store 上被编译和链接。 bitcode 允许苹果在后期重新优化我们程序的二进制文件,而不需要我们重新提交一个新的版本到 App Store 上。

    当我们提交程序到 App Store上时, Xcode 会将程序编译为一个中间表现形式( bitcode )。然后 App store 会再将这个 bitcode 编译为可执行的64位或32位程序。

    1. Xcode 7默认开启 Bitcode ,如果应用开启 Bitcode,那么其集成的其他第三方库也需要是 Bitcode 编译的包才能真正进行 Bitcode 编译

    2. 开启 Bitcode 编译后,编译产生的 .app 体积会变大(中间代码,不是用户下载的包),且 .dSYM 文件不能用来崩溃日志的符号化(用户下载的包是 Apple 服务重新编译产生的,有产生新的符号文件)

    3. 通过 Archive 方式上传 AppStore 的包,可以在Xcode的Organizer工具中下载对应安装包的新的符号文件

    iOS 9 中终于可以仅选择需要的内容 (Slicing) 下载了。

    这对用户来说是很大的利好,因为只需要升级到 iOS 9,就可以节省很多流量。对于开发者来说,并没有太多要做的事情,只需要使用 asset catalog 来管理素材标记 2x 3x 就可以了。

    给 App 瘦身的另一个手段是提交 Bitcode 给 Apple,而不是最终的二进制。Bitcode 是 LLVM 的中间码,在编译器更新时,Apple 可以用你之前提交的 Bitcode 进行优化,这样你就不必在编译器更新后再次提交你的 app,也能享受到编译器改进所带来的好处。Bitcode 支持在新项目中是默认开启的,没有特别理由的话,你也不需要将它特意关掉。

    应该有朋友在真机调试的时候发现在使用微博微信等第三方SDK的时候,会提示报错,

    XXXX’ does not contain bitcode. You must rebuild it with bitcode enabled

    (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor,

    or disable bitcode for this target. for architecture arm64

    Xcode默认开启bitcode模式,bitcode的理解应该是把程序编译成的一种过渡代码,然后苹果再把这个过渡代码编译成可执行的程序。bitcode也允许苹果在后期重新优化我们程序的二进制文件,可以直接理解为App瘦身。

    解决方式:

    1. 某些第三方库还不支持bitcode,我们只能等待库的开发者升级了此项功能.(这个是我们所不能掌握的,嘿嘿)

    2. 直接禁用bitcode,禁用的方法就是找到如下配置,选为NO.注意:iOS中bitcode是默认YES,watchOS中bitcodes是不让改的必须为YES。

    image.png
    1. 选为NO禁用

    3. 企业级分发

    在iOS8只是弹出一个窗问你是否需要让手机信任这个应用,但是在iOS9却直接禁止,如果真的想信任需要自己去手动开启。类似于Mac系统从未知开发者处下载的dmg直接打不开,然后要到系统偏好设置的安全性与隐私手动打开。

    解决方式:

    • 设置-->通用--->描述文件 自行添加信任.

    选择描述文件

    添加信任

    这个跟着找一下就找到了。

    1. URL scheme 引入白名单概念

    URL scheme一般使用的场景是应用程序有分享或跳其他平台授权的功能,分享或授权后再跳回来.

    在iOS8并没有做过多限制,但是iOS9需要将你要在外部调用的URL scheme列为白名单,才可以完成跳转.

    如果iOS9没做适配 会报如下错误 :

    canOpenURL: failed for URL : "mqzone://qqapp" - error: "This app is not allowed to query for scheme mqzone"

    例如在实现第三方登录时,不能直接跳转到相应的app直接获取权限.

    解决方式为:

    • 设置应用白名单 否则不能直接关联上你手机里的应用

      在info.plist中加入

      <key>LSApplicationQueriesSchemes</key> <array>

      <string>wechat</string>

      <string>weixin</string>

      <string>sinaweibohd</string>

      <string>sinaweibo</string>

      <string>sinaweibosso</string>

      <string>weibosdk</string>

      <string>weibosdk2.5</string>

      <string>mqqapi</string>

      <string>mqq</string>

      <string>mqqOpensdkSSoLogin</string>

      <string>mqqconnect</string>

      <string>mqqopensdkdataline</string>

      <string>mqqopensdkgrouptribeshare</string>

      <string>mqqopensdkfriend</string>

      <string>mqqopensdkapi</string>

      <string>mqqopensdkapiV2</string>

      <string>mqqopensdkapiV3</string>

      <string>mqzoneopensdk</string>

      <string>wtloginmqq</string>

      <string>wtloginmqq2</string>

      <string>mqqwpa</string>

      <string>mqzone</string>

      <string>mqzonev2</string>

      <string>mqzoneshare</string>

      <string>wtloginqzone</string>

      <string>mqzonewx</string>

      <string>mqzoneopensdkapiV2</string>

      <string>mqzoneopensdkapi19</string>

      <string>mqzoneopensdkapi</string>

      <string>mqzoneopensdk</string>

      <string>alipay</string>

      <string>alipayshare</string></array>

    1. statusBar

    以前我们为了能够实时的控制顶部statusbar的样式,可能会在喜欢使用

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]

    [[UIApplication sharedApplication]setStatusBarHidden:YES];

    但是这么做之前需要将 info.plist 里面加上View controller-based status bar appearance BOOL值设为NO,就是把控制器控制状态栏的权限给禁了,用UIApplication来控制。

    但是这种做法在iOS9不建议使用了,建议我们使用把那个BOOL值设为YES,然后用控制器的方法来管理状态栏比如。

    • (UIStatusBarStyle)preferredStatusBarStyle

    {

    return UIStatusBarStyleLightContent;

    }

    6. 字体

    iOS9中,中文系统字体变为了专为中国设计的“苹方”,字体有轻微的加粗效果,并且最关键的是字体间隙变大了!

    所以很多原本写死了width的label可能会出现“...”的情况。

    包括在很多时候我们自动计算行高行宽的时候出现偏差,导致一些不可知的错误

    解决方式:

    // 字体的大小

    CGSize size = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}];

    CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));

    加上向上取整 ceilf()就能解决了.

    7. AFNetworking

    为了迎合iOS新版本的升级, AFNetworking在3.0版本中删除了基于 NSURLConnection API的所有支持。

    如果你的项目以前使用过这些API,建议立即升级到基于 NSURLSession 的API的AFNetworking的版本。

    8.AVKit

    使用 AVPlayerViewController 或者 AVPlayerLayer 来播放视频。但如果你之前选择的方案是 MPMoviePlayerController 或者 MPMoviePlayerViewController 的话,你可能也需要尽早迁移到 AVKit 的框架下来,因为 Media Player 将在 iOS 9 被标记为 deprecated 并不再继续维护。

    9.UI Test

    在开发领域里,测试一直是保障产品质量关键。从 Xcode 4 以来,测试在 app 开发中的地位可谓是逐年上升。从 XCT 框架的引入,到测试 target 成为新建项目时的默认,再到去年加入的异步代码测试和性能测试。可以说现在 Xcode 自带的测试框架已经能满足绝大部分单元测试的需求了。

    但是这并不够。开发一个 iOS app 从来都是更注重 UI 和用户体验的工作,而简单地单元测试可以很容易地保证 model 层的正确,却很难在 UI 方面有所作为。如何为一个 app 编写 UI 测试一直是 Cocoa 社区的难题之一。之前的话有像是 KIFAutomating,甚至是 FBSnapshotTestCase 这种脑洞大开的方案。今年 Apple 给出了一个更加诱人的选项,那就是 Xcode 自带的 XCUITest 的一系列工具。

    和大部分已有的 UI 测试工具类似,XCUI 使用 Accessibility 标记来确定 view,但因为是 Apple 自家的东西,它可以自动记录你的操作流程,所以你只需要书写最后的验证部分就可以了,比其他的 UI 测试工具方便很多

    10 . Swift 2

    Swift 2 里主要的改动是错误处理方面的变化,Apple 从 Cocoa 传统的基于 NSError 错误处理方式变为了 throw catch 的异常处理机制。这个转变确实可以让程序更加安全,新增的 ErrorType 也很好地将错误描述进行了统一。但是在实际接触了一两天之后,在语法上感觉要比原来的处理写的代码多一些。可能是长久以来使用 NSError 的习惯导致吧,笔者还并没有能很好地全面接受 Swift 2 中的异常机制。不过这次 Apple 做的相对激进,把 Cocoa API 中的 error 全数替换成了 throw。所以不管情不情愿,转型到异常处理是 Swift 开发者必须面对的了。

    另外 Apple 新加了一些像是 guard 和 defer 这样的控制流关键字,这在其他一些语言里也是很实用的特性,这让 Swift 的书写更加简化,阅读起来更流畅。为了解决在运行时的不同 SDK 的可用性的问题,Apple 还在 Swift 2 里加入了 avaliable 块,以前我们需要自己去记忆 API 的可用性,并通过检查系统版本并进行对比来做这件事情。现在有了 avaliable 检测,编译器将会检查出那些可能出现版本不匹配的 API 调用,app 开发的安全性得到了进一步的保障。为了让整个 SDK 更适合 Swift 的语法习惯,Apple 终于在 Objective-C 中引入了泛型。这看似是 Objective-C 的加强,但是实际上却实实在在地是为 Swift 一统 Apple 开发开路。有了 Objective-C 泛型以后,用 Swift 访问 Cocoa API 基本不会再得到 AnyObject 类型了,这使得 Swift 的安全特性又上了一层台阶。

    11 .iOS9 下使用 Masonry 会引起崩溃的一种情况

    我们在使用时候一直将 leading 与 left 划为等号,这样做在 iOS8(及以前)上是正常的,但在 iOS9 上这样的观念可能会引起崩溃,比如:

    make.left.equalTo(self.mas_leading).offset(15);

    应该为:

    make.left.equalTo(self.mas_left).offset(15);

    同理 mas_training 也需要改为right

    12 .navigationController状态栏样式新的设置方法

    如果你按照上面的方法设置了,但还是不行。八成是 rootViewController 设置的问题,你必须设置 rootViewController,编译器才会去 rootViewController 中重载 preferredStatusBarStyle 方法。

    另外当你在 appdelegate 中将 navigationController 设为 rootViewController 的时候:

    self.window.rootViewController = self.navigationController;

    因为 rootViewController 变为了 navigationController,你在 ViewController 里重写 preferredStatusBarStyle 方法是不会起作用的。所以最好的方法是

    • (void)viewDidLoad

    {

    [super viewDidLoad];

    self.title = @"微博@iOS程序犭袁";

    self.navigationController.navigationBar.barStyle = UIBarStyleBlack;

    }

    如果你还是想重写 preferredStatusBarStyle 方法来达到作用,那最好使用分类来解决:

    .h文件:

    //

    // UINavigationController+StatusBarStyle.h

    // 微博@iOS程序犭袁

    //

    // Created by https://github.com/ChenYilong/iOS9AdaptationTips/ on 15/6/8.

    // Copyright (c) 2015年 http://weibo.com/luohanchenyilong/ . All rights reserved.

    //

    import <UIKit/UIKit.h>

    @interface UINavigationController (StatusBarStyle)

    @end

    .m文件:

    //

    // UINavigationController+StatusBarStyle.m

    // 微博@iOS程序犭袁

    //

    // Created by https://github.com/ChenYilong/iOS9AdaptationTips/ on 15/6/8.

    // Copyright (c) 2015年 http://weibo.com/luohanchenyilong/ . All rights reserved.

    //

    import "UINavigationController+StatusBarStyle.h"

    @implementation UINavigationController (StatusBarStyle)

    • (UIStatusBarStyle)preferredStatusBarStyle

    {

    //also you may add any fancy condition-based code here

    return UIStatusBarStyleLightContent;

    }

    @end

    我在仓库里给出了 navigation 的设置方法,见Demo4。

    参考链接: preferredStatusBarStyle isn't called--For anyone using a UINavigationController:

    13.使用了 HTML 的 iframe 元素可能导致无法从 Safari 跳转至 App

    我们都知道,从网易新闻分享一条新闻到QQ,然后从QQ中打开链接再用safari打开链接,在iOS8上,这个时候会跳转到网易新闻App。但是现在 (2015年09月23日)版本的网易新闻在 iOS9 就不能正常跳转,会跳转到 App Store 页面并提示要不要打开 App Store。

    这是很可能是因为使用了 HTML 的 iframe 元素,并将自定义的链接放进了该元素中

    举例说明:

    image.png

    我之前写的一个 Demo: 模仿 《简书 App》 的效果:在html中跳转到App中的对应页面,并能从App跳转到原来的网址,在例子中直接调用自定义链接在 iOS9上是可以跳转到 App 中的,然而,如果用 iframe 元素包起来就会变不可用。

    参考链接:

    1. HTML 的iframe 标签

    2. iOS 9 safari iframe src with custom url scheme not working

    14.在didFinishLaunchingWithOptions结束后还没有设置window的rootViewController会导致崩溃

    iOS9 不允许在 didFinishLaunchingWithOptions 结束了之后,还没有设置 window 的rootViewController 。 也许是 Xcode7 的编译器本身就不支持。

    崩溃时的控制台日志提示:

    *** Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UIApplication.m:3294

    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Application windows are expected to have a root view controller at the end of application launch'

    *** First throw call stack:

    /省略/

    libc++abi.dylib: terminating with uncaught exception of type NSException

    (lldb)

    解决的方法是先设初始化个值,之后再赋值替换掉:

    UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreenmainScreen].bounds];

    window.rootViewController = [[UIViewController alloc] init];

    尤其注意一种情况,在 iOS8以前,我们有时候会通过在 AppDelegate 中添加另一个 UIWindow ,并修改其 Level 来达到 addSubview 的效果,因而也不设置 window 的 rootViewController ,而是把它直接以视图的形式展示了,则在 iOS8 上是警告,在 iOS9 上就崩溃了。

    • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.window.backgroundColor = [UIColor yellowColor];

    [self.window makeKeyAndVisible];

    UIWindow *normalWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    normalWindow.backgroundColor = [UIColor blueColor];

    normalWindow.windowLevel = UIWindowLevelAlert;

    [normalWindow makeKeyAndVisible];

    return YES;

    }

    这种情况,在 didFinishLaunchingWithOptions 需要修改原来的策略,将第二个 window 类型改为其他类型,比如 viewController 类型、navigation 类型、tabbarController 类型等

    Xcode 7+

    ·泛型
    
         因为Swift中集合的元素都是有类型的, 为了和Swift更好的兼容, 新版本里, OC开始支持泛型, 主要是在各种集合类型(比如数组, 集合, 字典)中使用.
    

    这无疑是本次最重大的改进,有了泛型后终于可以指定容器类中对象的类型了:

    <colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
    |

    1

    2

    |

    NSArray<NSString *> *strings = @[@"sun", @"yuan"];

    NSDictionary<NSString *, NSNumber *> *mapping = @{@"a": @1, @"b": @2};

    |

    返回值的 id 被替换成具体的类型后,令人感动的代码提示也出来了:

    假如向泛型容器中加入错误的对象,编译器会不开心的:

    image.jpeg

    系统中常用的一系列容器类型都增加了泛型支持,甚至连 NSEnumerator 都支持了,这是非常 Nice 的改进。和 Nullability 一样,我认为最大的意义还是丰富了接口描述信息,对比下面两种写法:

    <colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
    |

    1

    2

    |

    @property (readonly) NSArray *imageURLs;

    @property (readonly) NSArray<NSURL *> *imageURLs;

    |

    不用多想就清楚下面的数组中存的是什么,避免了 NSString 和 NSURL 的混乱。

    (自定义泛型类)

          比起使用系统的泛型容器,更好玩的是自定义一个泛型类,目前这里还没什么文档,但拦不住我们写[测试](http://lib.csdn.net/base/softwaretest "软件测试知识库")代码,假设我们要自定义一个 Stack 容器类:
    

    <colgroup><col style="width: 34px;"><col style="width: 523px;"></colgroup>
    |

    1

    2

    3

    4

    5

    |

    @interface Stack<ObjectType> : NSObject

    • (void)pushObject:(ObjectType)object;

    • (ObjectType)popObject;

    @property (nonatomic, readonly) NSArray<ObjectType> *allObjects;

    @end

    |
    | | |

          这个 ObjectType 是传入类型的 placeholder,它只能在 @interface 上定义(类声明、类扩展、Category),如果你喜欢用 T 表示也 ok,这个类型在 @interface 和 @end 区间的作用域有效,可以把它作为入参、出参、甚至内               部 NSArray 属性的泛型类型,应该说一切都是符合预期的。我们还可以给 ObjectType 增加类型限制,比如:
    

    <colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
    |

    1

    2

    3

    4

    |

    // 只接受 NSNumber * 的泛型

    @interface Stack<ObjectType: NSNumber *> : NSObject

    // 只接受满足 NSCopying 协议的泛型

    @interface Stack<ObjectType: id<NSCopying>> : NSObject

    |

    若什么都不加,表示接受任意类型 ( id );当类型不满足时编译器将产生 error。

    实例化一个 Stack,一切工作正常:

    image.jpeg

    对于多参数的泛型,用逗号隔开,其他都一样,可以参考 NSDictionary 的头文件。

    • 可空性标注

      因为Swift的代码里面的主要类型默认是没有空值一说的, 只有可选类型才可以为空. 为了和Swift更好的结合, Objective-C中也加入了 可空性标注 , 可以标注是否期望一个值是否可空.、

    • __kindof修饰符

      通过使用 kindof 声明某对象是某种类型, 让编译器知道对象是某种类型或者该类型的子类, 可以用在泛型参数里. 使用 kindof 对类型进行约束, 比指定某种类型或者id类型更灵活一些.

    __kindof 这修饰符还是很实用的,解决了一个长期以来的小痛点,拿原来的 UITableView 的这个方法来说:

    <colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
    |

    1

    |

    • (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;

    |

    使用时前面基本会使用 UITableViewCell 子类型的指针来接收返回值,所以这个 API 为了让开发者不必每次都蛋疼的写显式强转,把返回值定义成了 id 类型,而这个 API 实际上的意思是返回一个 UITableViewCell 或 UITableViewCell 子类的实例,于是新的 __kindof 关键字解决了这个问题:

    <colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
    |

    1

    |

    • (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;

    |

    既明确表明了返回值,又让使用者不必写强转。再举个带泛型的例子,UIView 的 subviews 属性被修改成了:

    <colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
    |

    1

    |

    @property (nonatomic, readonly, copy) NSArray<__kindof UIView *> *subviews;

    |

    这样,写下面的代码时就没有任何警告了:

    <colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
    |

    1

    |

    UIButton *button = view.subviews.lastObject;

    |

    • 地址消毒剂

      Xcode7能够在编译应用时加入地址消毒剂, 用以帮助捕获和调试内存冲突. 堆栈缓冲溢出, 野指针等内存冲突导致的崩溃Objective-C和C代码很容易产生. 内存问题可能导致app崩溃, 也可能让app发生诡异的行为. 由于难以复现, 并且bug现象和源头可能相距很远(比如登陆功能有野指针可能导致商品的名称显示不正常), 内存问题很难追踪.

      在build scheme里面启用地址消毒剂, 你就可以在发生问题的时候定位内存地址. Xcode同时也会提供诸如地址和对象的关系, 对象分配和回收的信息, 从而帮助你定位和解决为题. 地址消毒剂的性能很好. 支持模拟器和真实设备, 支持iOS和 OS X.

    • UI 录制

      UI test方法可以通过录制UI交互操作的方式创建. 当用户和应用交互的时候, Xcode在你的测试方法里面注入代码, 这些代码找到你app的UI元素, 访问他们的属性, 调用他们的事件.

    • 正确性和性能

      XCTest现在为定位UI元素, 访问元素的属性, 调用事件提供了丰富的特性. 在UITest中, assert, 性能监视等同样支持.

    • 代码覆盖率

      在scheme里启用代码覆盖率功能, 就可以对代码覆盖率进行可视化. 在测试报告里可以看到哪个文件里的哪个函数的哪行代码是执行了还是没执行.代码编辑器也可以显示代码的覆盖率信息, 让你看到在一此测试中哪行代码执行了, 哪行代码没执行.

    • Xcode Server.

      Xcode的测试功能已经和Xcode Server完整的集成. 在Xcode Server上你在一个hands-off(放手, 类似于骑自行车大撒把)的环境里, 在多个设备上执行测试, 反复的执行, 统一和更好的评估app的正确性和性能. 新的Xcode Server 报表格式会显示一个项目中的趋势, 回归反复进行的测试.

      在你自己的设备上开发

      在Xcode7里面, 不再需要购买开发者以及进行繁琐的设置, 你就可以在任意的设备上进行开发和调试了. 只需要注册一个Apple Id.

    ·ios9之后的Top Layout Guide与Bottom Layout Guide

    http://blog.csdn.net/moon_prince2013/article/details/50067663

    image.png image.png

    勾选第二个 改成bottom space

    1.状态栏的警告

    <Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

    <Error>: CGContextTranslateCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

    <Error>: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

    出错原因:设置 app 的状态栏样式的时候,使用了旧的方式,在 info.plist 里面的 View controller-based status bar appearance 默认会为 YES,即使不设置也是 YES,但一般 iOS6 的时候为了设置状态栏样式,需要将其设为NO,iOS7,8也兼容,但是到了iOS9 就会报警告。

    解决办法:

    删除原先的设置代码,通常老的设置方式是这样的:

    //设置状态栏的白色

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    删除的原因见下:

    // Setting the statusBarStyle does nothing if your application is using the default UIViewController-based status bar system.

    @property(readwrite, nonatomic) UIStatusBarStyle statusBarStyle NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController preferredStatusBarStyle]");

    • (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController preferredStatusBarStyle]");

    修改方式是在 Info.plist 文件中做如下修改:

    将 View controller-based status bar appearance 删除(默认为 YES),或设置为YES:

    对应的 plist 里的 XML源码:

    <key>UIViewControllerBasedStatusBarAppearance</key>

    <true/>

    看起来长这样:

    image.jpeg

    然后使用新的方式来实现状态栏的样式:

    • (UIStatusBarStyle)preferredStatusBarStyle;

    • (UIViewController *)childViewControllerForStatusBarStyle;

    • (void)setNeedsStatusBarAppearanceUpdate

    比如,你想将状态栏设置为白色,就可以这样写:

    //设置状态栏的白色

    -(UIStatusBarStyle)preferredStatusBarStyle

    {

    return UIStatusBarStyleLightContent;

    }

    记得要 clean 下或者删除应用程序重新运行

    2.运行报错 there is an intenal API error

    Xcode7 调试 iOS8.x 的真机,需要确保项目名改为英文,中间含有中文会报错 there is an intenal API error

    按照下面的步骤检查:

    bulid settings -> packaging -> product name

    相关文章

      网友评论

          本文标题:历代iOS版本 — iOS9

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