iOS10 适配、Xcode8配置总结②

Xcode8 新特性html

Interface Builderios

随着14年的iPhone6和6P出来以后,iPhone的屏幕尺寸也愈来愈多,屏幕适配是一个须要解决的问题,之后不必定苹果又出什么尺寸的iPhone呢。api

在iPhone6和6P发布的同一年,苹果推出的Xcode6中在原有的Auto layout的基础上,添加了Size Classes新特性,经过这个新特性可使用一个XIB或者SB文件,适配不一样的屏幕以及iPhone和iPad两种设备。数组

在Xcode8中,苹果推出了更增强大的可视化编辑工具预览功能,能够在不运行App的状况下,预览当前XIB或SB在不一样屏幕尺寸下的显示。(这个功能我记得以前Xcode就有,只是隐藏的比较深,苹果如今给拿到外面了)app

选择一个XIB文件进去,点击下面红框的位置,会出现从3.5寸-5.5寸一系列屏幕尺寸的选项。直接点击不一样屏幕尺寸,以及横竖屏选项,切换不一样的屏幕显示。在iPad上还能够选择是否分屏,功能很是强大。框架

21.png

Interface Builder异步

在右边有一个Vary for Traits选项,点击这个选项就能够同时显示全部可选的屏幕样式,功能和上面图片都同样,只是显示上看起来比较多。函数

22.png

Interface Builder工具

还有一点,新建立的XIB控件尺寸,再也不是以前600*600的方块了,而是默认是6s的长方形XIB文件,看起来舒服多了。字体

Target中General的变化

在Xcode8以前,都须要本身设置证书和描述文件。若是设置出现错误的状况下,还能够经过点击Fix issue来修复这个错误。但这有个问题就在于,Fix issue选项并非那么好用,有的时候设置是正确的这里也提示须要Fix issue。

可能苹果也意识到这个问题的存在,在Xcode8中能够经过Automatically manage signing选项,让苹果为咱们管理证书和配置文件,设置也都是由苹果来完成的。在Xcode8中新建项目,这个选项默认是被勾选的。

23.png

Automatically manage signing

从上面图中能够看到,苹果帮咱们自动管理了证书和配置文件。并且在以前的项目中,若是想要设置安装后显示在手机上的App名字,还须要本身到Info.plist文件中,修改Display Name字段,而如今直接在General中就能够作修改,这个修改和Info.plist是同步的。

可是,若是我想本身管理证书和描述文件呢?只须要去掉Automatically manage signing选项。

24.png

Automatically manage signing

若是本身到Build Settings中手动设置证书和描述文件,能够发现Provisioning Profile选项已经被标明为Deprecated,也就是苹果并不推荐手动设置。

Xcode插件

升级Xcode8以后会发现,在Xcode8中全部第三方插件都失效了,而且连以前菜单栏的插件选项也不存在了。在以前不少iOS开发者,都是经过Alcatraz来管理插件的,如今Alcatraz也是不可用的。可是Xcode8自身也对编译器进行了升级,将一些比较好的插件功能加入到Xcode中,例如单行高亮显示等。

在Xcode8中支持了开发插件工程,而且为咱们提供了一个插件模板,开发的插件能够上传到App Store下载。苹果这么作有一个缘由在于,以前Xcode和插件是运行在同一个进程的,因此插件的崩溃也会致使Xcode崩溃。苹果如今将插件做为一个单独的应用程序,分开进程运行,不会对Xcode带来其余影响。

25.png

Xcode Source Editor Extension

Runtime Issues

在开发过程当中,由于语法或明显的代码错误(例如Retain Cycle),编译器能够发现并报黄色或红色警告。可是一些由于代码逻辑致使的错误,编译器并无办法找到。例以下面的这句代码,由于代码逻辑的问题致使两个数组相互引用,都不能释放。

26.png

数组循环引用

这时候能够经过Xcode8提供的Runtime Issues新特性,查找到运行过程当中出现的问题,并经过Graph的方式将问题可视化的展示给开发者。

27.png

Runtime Issues

Debug Memory Graph

在Xcode6中出现了Debug View Hierarchy新特性,能够经过其调试当前App的视图层级,查找UI相关的bug很是方便。在Xcode8中苹果为开发者提供了Debug Memory Graph特性,经过这个新特性,能够直接选择一个对象,查看与其相关的内存关系。

28.png

Debug Memory Graph

Debug Memory Graph和Runtime Issues能够配合使用,经过Debug Memory Graph分析内存关系完成后,点击Runtime Issues能够看到已经发现的内存问题。

Swift 3

Xcode8带来了新版本的Swift3,新版本的Swift变化较大,若是旧版的Swift项目在Xcode8上编译可能会失败。对此,苹果为开发者提供了Swift迁移工具,据说不太好用(我没用过这个工具)。

若是不想马上就迁移到Swift3,能够在Builder Settings中进行设置,选择Use Legacy Swift Language Version设置为YES,就能够继续使用旧版本的Swift2.3。

29.png

Use Legacy Swift Language Version

其余更新

  1. Xcode新版字体,SF Mono Regular字体。更新Xcode以后我比较喜欢这种字体,看起来代码很是工整。

  2. 被编辑的行高亮显示。以前Xcode有个插件就是这个功能,Xcode8把高亮功能集成进来了,使用起来很方便。

  3. 最新版的API文档,展现样式发生了很大的改变。

  4. 更方便的生成文档(就是喵神写的VVDocumenter),在Xcode8中能够将光标放在方法上面,经过option + command + /快捷键生成文档注释。

Xcode 8适配

XIB和Storeboard适配

在Xcode8以前,建立一个XIB或SB文件,都是一个600*600的方块XIB文件。在Xcode8以后,建立的XIB文件默认是6s尺寸的大小。

可是Xcode8打开以前旧项目的XIB或SB文件时,会弹出下面的弹框, 这时候通常直接选择Choose Device便可。

30.png

Choose an initial device view

可是这样有个问题,若是Xcode8打开过这个XIB文件,并选择Choose Device以后。其余的Xcode8如下版本的编译器,将没法再打开这个文件,会报如下错误:

The document “ViewController.xib” requires Xcode 8.0 or later. This version does not support documents saved in the Xcode 8 format. Open this document with Xcode 8.0 or later.

有两种方法解决这个问题:

  1. 你同事也升级Xcode8,比较推荐这种方式,应该迎接改变。

  2. 右击XIB或SB文件 -> Open as -> Source Code,删除xml文件中下面一行字段。

31.png

编译错误

升级Xcode以后,Xcode8对以前的一些修饰符和语句不兼容,会致使一些编译错误。这种错误致使的缘由不少,这里大体列几条,各位仍是根据自身遇到的状况作修改吧。

  1. 以前一些泛型相关的修饰符,nullable之类的有的会报错。

  2. CAAnimation及其子类,设置代理属性后,必须在@interface()遵照代理,不然报错,等等。

权限适配

这应该算iOS10系统适配的范畴,最近这两个都在弄,因此就直接和Xcode8适配一块儿写出来了。

在iOS10以后须要在Info.plist中,添加新的字段获取权限,不然在iOS10上运行会致使崩溃。下面是一些经常使用的字段,若是有缺乏的麻烦各位评论区补充一下。

222.png

参考资料:developer.apple

推送通知

苹果的推送在以前iOS8和iOS9的时候就发生过大的更新,推送功能愈来愈强大。在iOS10以后苹果推出了UserNotifications框架,能够经过这个框架更好的控制推送通知,能够更新、修改锁屏页面的推送消息,能够添加图片等功能。

可是在用Xcode8打包后,而且不对代码进行修改的状况下,会发现打包后苹果发来了一封邮件。这封邮件大概意思是若是须要使用推送通知,须要对代码作修改,不然将不能使用推送通知。

33.png

Push Notifications

这是由于在Xcode8以后,若是须要使用Push Notifications的功能,须要勾选Capabilities -> Push Notifications为YES,不然进行远程推送就会有问题,而且会收到苹果发来的这封邮件。

删除系统log

升级Xcode8以后,在调试和运行过程当中,发现控制台打印了不少不认识的log,这些log是系统打印的,和开发者不要紧。可是这么多log看着比较乱,怎么屏蔽掉呢?

subsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0

在Target -> Edit Scheme -> Run -> Arguments中,添加OS_ACTIVITY_MODE字段,并设置为Disable便可。

35.png

OS_ACTIVITY_MODE

顺便提一下,这两天在设置log选项的时候,发现能够经过在Arguments中设置参数,打印出App加载的时长,包括总体加载时长,动态库加载时长等。

在Environment Variables中添加DYLD_PRINT_STATISTICS字段,并设置为YES,在控制台就会打印加载时长。

38.png

控制台打印信息

awakeFromNib报警告

老项目在Xcode8中,有些重写awakeFromNib方法的地方,会报下面的错误。这是由于没有调用super的方法致使的,还好我平时都是调用super的,我代码目前还没出问题。

1

Method possibly missing a [super awakeFromNib] call

 

 

苹果在iOS 2中引入了openURL:方法来进行APP间的跳转。不过在iOS 9中,隐私控制已禁止开发者经过openURL:方法查询设备上是否安装了哪些APP应用。苹果禁止开发者查询设备上是否安装了某款APP。在iOS 10中,苹果弃用了openURL,转而用openURL:options:completionHandler:替代。简单介绍如何在iOS 10中进行APP之间的跳转。

iOS 10中的新功能

苹果在What's New in iOS文档的UIKit部分中指出:

新的UIApplication方法openURL:options:completionHandler:能够异步执行并在主队列中执行完成后进行回调(此方法替换原来的openURL:)。

如今被废弃的方法必须传入启动APP的URL并返回布尔值来标识成功或是失败。

 

1

2

3

4

5

// Objective-C

- (BOOL)openURL:(NSURL*)url

 

// Swift

open func canOpenURL(_ url: URL) -> Bool

iOS 10中的新方法:

 

1

2

3

4

5

6

7

// Objective-C

- (void)openURL:(NSURL*)url options:(NSDictionary *)options

  completionHandler:(void (^ __nullable)(BOOL success))completion

   

// Swift

open func open(_ url: URL, options: [String : Any] = [:],

  completionHandler completion: (@escaping (Bool) -> Swift.Void)? = nil)

如今变为三个参数

  • 打开APP的URL

  • 可选字典参数(请参见如下有效条目)。传入一个空字典能够达到openURL:同样的行为。

  • 执行成功后completionhandler在主队列中回调。若是你并不关心它的返回状态也能够传空。

在iOS10中打开URL

若是你有一个iOS 10应用程序也就意味着你不须要关心它的可选参数及完成回调函数返回的状态并中止对Xcode的抱怨。

 

1

2

3

4

5

6

// Objective-C

UIApplication *application = [UIApplication sharedApplication];

[application openURL:URL options:@{} completionHandler:nil];

 

// Swift

UIApplication.shared.open(url, options: [:], completionHandler: nil)

在项目实践中,若是你仍然兼容iOS9及更早的版本,你确定会想用回之前的openURL 老方法。下面来看一段代码是如何使用completionHandler来检查APP打开状态。先上一段Object-C代码:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

- (void)openScheme:(NSString *)scheme {

  UIApplication *application = [UIApplication sharedApplication];

  NSURL *URL = [NSURL URLWithString:scheme];

 

  if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) {

    [application openURL:URL options:@{}

       completionHandler:^(BOOL success) {

      NSLog(@"Open %@: %d",scheme,success);

    }];

  else {

    BOOL success = [application openURL:URL];

    NSLog(@"Open %@: %d",scheme,success);

  }

}

 

// Typical usage

[self openScheme:@"tweetbot://timeline"];

我为option参数传入一个空的字典,除了只是在成功回调方法里只是打印了一下日志之外,并无写任何有用的代码。如下是Swift版本:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

func open(scheme: String) {

  if let url = URL(string: scheme) {

    if #available(iOS 10, *) {

      UIApplication.shared.open(url, options: [:],

        completionHandler: {

          (success) in

           print("Open \(scheme): \(success)")

       })

    else {

      let success = UIApplication.shared.openURL(url)

      print("Open \(scheme): \(success)")

    }

  }

}

 

// Typical usage

open(scheme: "tweetbot://timeline")

Options 参数

UIApplication 头文件为options字典列出了一个key:

  • UIApplicationOpenURLOptionUniversalLinksOnly:若是这个要打开的URL有效,而且在应用中配置它布尔值为true(YES)时才能够打开,不然打不开。

为了覆盖默认行为,建立一个设置key值了True的字典做为参数传入:

 

1

2

3

4

5

6

7

// Objective-C

NSDictionary *options = @{UIApplicationOpenURLOptionUniversalLinksOnly : @YES};

[application openURL:URL options:options completionHandler:nil];

 

// Swift

let options = [UIApplicationOpenURLOptionUniversalLinksOnly : true]

UIApplication.shared.open(url, options: options, completionHandler: nil)

以上面示例,若是我设置它为true并打开URL:https://twitter.com/kharrison 时, 若是我并无安装Twitter app那它就会失败,同时会调用safari来打开这个连接。

 

 

原文:http://www.cocoachina.com/ios/20161024/17830.html

原文:http://www.cocoachina.com/ios/20161024/17824.html