iOS9与Xcode7新特性一览

iOS9与Xcode7正式版已经发行有一段时间了,网上各位大神也陆续推出了他们对于新特性的blog。今天抽时间对这些新特性做一个归纳和总结。方便后面慢慢研究和使用。

iOS9

多任务

  • 滑动覆盖Slide Over 与 分屏多任务Split View
    以上两者目前都只在iPad中才有,在Xcode7中,info.plist里面已经默认支持了这两个功能,如果你是一些游戏或者只能支持全屏的应用,可以info.plist 中添加 UIRequiresFullScreen 项并将其设为YES,从而禁止分屏功能。
    而如果我们要支持这两个功能的话,更多的工作是布局与适配,可以使用第三方现在的布局库Masonry或者PureLayout
    在UIViewController的 -willTransitionToTraitCollection:withTransitionCoordinator:-viewWillTransitionToSize:withTransitionCoordinator:里尽情地使用自动布局吧。

  • 画中画Picture in Picture
    画中画也是iOS9之后为iPad推出的一个多任务的功能。目前仅支持iOS里面的App播放或者是使用safari里面的webkit播放的视频。
    在iOS App里面使用这个功能的话,首先要设置后台播放的功能,这个我在AirPlay三两事的博客中有指明,就是

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
同时在Xcode中的Background Modes勾选Audio And AirPlay.

使用系统提供的AVPlayerLayer,其有一个属性allowsPictureInPicturePlayback默认为YES,是用来播放画中画的,如果你不想支持这个功能,可以把它置为NO.


应用瘦身App Thinning

  • App Slicing
    苹果推出的App瘦身计划,从iOS9.0.2之后开始生效。32位的机器与64位的机器会根据自身的需要,自动加载32位或者64位的内容,之前一直是混在一起的,占用了大量的空间。

  • one-demand resources 按需下载应用资源
    应用可以根据用户的实际情况来下载内容。

  • Bitcode
    上传应用是不必提交预编译的二进制文件,只需上传中间文件intermediate representation
    用户下载时根据实际需要来下载32位或者64位程序。
    在Xcode7中的Build Setting里面有一个Enable Bitcode选项,如果你主动把其置为NO,则可关闭这一特性。


Spotlight搜索

现在Spotlight不仅可以搜索系统自己的程序和内容,还可以搜索开发者的App里面的内容,其提供了相应的API,目前微信和QQ都已经实现。
这儿有一篇写得还不错的博客.其核心代码就是要建立数据索引,便于查找数据,这也是我们在使用Spotlight的真正困难的地方,索引其实细分的话,主要有正排索引倒排索引

  • NSUserActivity
    NSUserAcitivity 在介绍 iOS8 的 Handoff 时引入,iOS9 中允许对这些 activities 进行搜索。你可以提供元数据给这些 activities, 这意味着 sptlight 可以索引这些内容。类似于浏览器展示网页的做法(你打开过的历史页面被记录了下来),用户可以快速的在 Spotlight中搜索,打开最近的 activities。

  • Core Spotlight API
    其核心代码是创建索引

- (void)saveData{   
     NSMutableArray *seachableItems = [NSMutableArray new];   
     [self.tableData enumerateObjectsUsingBlock:^(NSString *__nonnull obj, NSUInteger idx, BOOL * __nonnull stop) {       
          CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:@"views"];       
          attributeSet.title = obj;     
          attributeSet.contentDescription = [NSString stringWithFormat:NSLocalizedString(@"a easy way to open %@", nil),obj]; 
          UIImage *thumbImage = [UIImage imageNamed:[NSString stringWithFormat:@"icon_%@.png",obj]];
          attributeSet.thumbnailData = UIImagePNGRepresentation(thumbImage);//beta 1 there is a bug 
          CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:obj                                                                                                                                    domainIdentifier:@"com.kdanmobile.CoreSpotlightDemo"                                                                                                        attributeSet:attributeSet];
          [seachableItems addObject:item];    
       }];
      [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:seachableItems
                                                     completionHandler:^(NSError * __nullable error) {                                                              if (!error)                                                        
                   NSLog(@"%@",error.localizedDescription);                                               
        }];
  }   

以及点击Spotlight结果时的跳转逻辑处理

- (BOOL)application:(nonnull UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * __nullable))restorationHandler{

NSString *idetifier = userActivity.userInfo[@"kCSSearchableItemActivityIdentifier"];

UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;

[navigationController popToRootViewControllerAnimated:YES];

CoreSpotlightTableViewController *coreViewController = [[navigationController viewControllers] firstObject];

[coreViewController showViewControllerWithIdentifier:idetifier];

return YES;

} 
  • Web Markup
    Web Markup 允许应用镜像自己的内容,并在 Spotlight 中建立索引。用户并不需要应用安装在自己的设备上来展示搜索结果。苹果会自己去抓取你网站上打了 markup 的内容,这些内容稍后会提供给 Safari 和 Spotlight。
    详细内容请参考iOS 9 Search and Universal Links

  • Universal Links通用链接
    iOS 9 的新特性 Universal Links 真正支持网页链接与 App 之间的联动,只要 App 提供了该特性支持,用户就可以实现「直接从 App 里打开相应链接」的效果。
    以支持了 Universal Links 的 Twitter 为例,我在 iMessage、Telegram 里打开一条 Twitter 链接,iOS 9 系统会自动检测并默认使用 Twitter App 来打开这条内容,而无需通过 Safari 去浏览体验欠佳的网页版。
    不仅如此,我们还在 Safari 中测试了 New Yorker 文章的 Twitter 分享按钮,也会直接启动 Twitter App 来发送分享 Tweet……
    这里有一篇不错的教程


UI相关

  • 引入UIStackView

UIStackView 类提供了一个高效的接口用于平铺一行或一列的视图组合。Stack视图使你依靠自动布局的能力,创建用户接口使得可以动态的调整设备朝向、屏幕尺寸及任何可用范围内的变化

axis(轴向) 属性决定了 stack 的朝向,只有垂直或水平;
distribution(分布) 属性决定了其管理的视图在沿着其轴向上的布局;
alignment(对齐) 属性决定了其管理的视图在垂直于其轴向上的布局;
spacing(空隙) 属性决定了其管理的视图间的最小间隙;
baselineRelativeArrangement 属性决定了其视图间的垂直间隙是否根据基线测量得到;
layoutMarginsRelativeArrangement 属性决定了 stack 视图平铺其管理的视图时是否要参照它的布局边距

  • 公开了CASpringAnimation
let spring = CASpringAnimation(keyPath: "position.x")
        spring.damping = 5;
        spring.stiffness = 100;
        spring.mass = 1;
        spring.initialVelocity = 0;
        spring.fromValue = label.layer.position.x;
        spring.toValue = label.layer.position.x + 50;
        spring.duration = spring.settlingDuration;
        label.layer.addAnimation(spring, forKey: spring.keyPath);

mass: 质量
stiffness:刚度系数(劲度系数/弹性系数)
damping:阻尼系数
initialVelocity:初始速率

  • UICollectionView相关内容更新
    UICollection现在有重新排列元素的能力了,之前手动对里面的排序是一件比较麻烦的事情,不过现在已经有了现成的代码,越来越感叹程序员没有什么含金量了(自嘲),有一篇博客介绍得比较详细

  • UIDynamics中引入UiFieldBehavior效果
    iOS9可以对凸面的Path类型物体模拟物理效果,UiFieldBehavior指在某个区域内添加一些扰动,使得物体随意地飘动,这儿有一篇博客详细地介绍这一点。


3D Touch

3D Touch通过区分轻按和重按来进行不同的用户交互,github上面有人开发了一款插件,可以在模拟器上进行3DTouch的交互操作,关于3D Touch有一篇好的文章讲得比较详细。

  • Peek and Pop

Peek and Pop需要在UIViewController里面注册UIViewControllerPreviewingDelegate

 - (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)context viewControllerForLocation:(CGPoint) point  
  {  
      UIViewController *childVC = [[UIViewController alloc] init];  
      childVC.preferredContentSize = CGSizeMake(0.0f,300f);  

      CGRect rect = CGRectMake(10, point.y - 10, self.view.frame.size.width - 20,20);  
      context.sourceRect = rect;  
      return childVC;  
  }  
  - (void)previewContext:(id<UIViewControllerPreviewing>)context commitViewController:(UIViewController*)vc  
  {  
      [self showViewController:vc sender:self];  
  }  
  @end
  • Quick Actions

类似于windows系统下的右键,但侧重点又不同,其旨在减少操作路径,达到更好的用户体验。
方式一:静态设置
首先我们要在info.plist里面加入UIApplicationShortcutItems数组,数组里面有一些选项
必填项(下面两个键值是必须设置的):
UIApplicationShortcutItemType 这个键值设置一个快捷通道类型的字符串
UIApplicationShortcutItemTitle 这个键值设置标签的标题

选填项(下面这些键值不是必须设置的):
UIApplicationShortcutItemSubtitle 设置标签的副标题
UIApplicationShortcutItemIconType 设置标签Icon类型
UIApplicationShortcutItemIconFile 设置标签的Icon文件
UIApplicationShortcutItemUserInfo 设置信息字典(用于传值)

方式二:动态添加
我们也可以通过代码来自由的添加Quick Actions

//创建
    UIApplicationShortcutItem * item = [[UIApplicationShortcutItem alloc]initWithType:@"two" localizedTitle:@"第二个标签" localizedSubtitle:@"看我哦" icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypePlay] userInfo:nil];
    添加
    [UIApplication sharedApplication].shortcutItems = @[item];

然后我们可以在代码中监听用户的点击事件
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0);
这里有一点需要注意:我们在app的入口函数:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
也需要进行一下判断,在launchOptions中有UIApplicationLaunchOptionsShortcutItemKey这样一个键,通过它,我们可以区别是否是从标签进入的app,如果是则处理结束逻辑后,返回NO,防止处理逻辑被反复回调。


其它

  • URL Scheme调整 在iOS9中,URL scheme的跳转功能,需要在工程中的info配置文件中添加LSApplicationQueriesSchemes属性,并把支持的跳转URL scheme添加进来。 这儿有一篇老外的博客
  • 全面使用HTTPS 当然也可以在Xcode工程中的info里面配置不使用http,配置方法为添加NSAppTransportSecurity属性,设置NSAllowsArbitraryLoadsYES.这样就可以使用Http了。
  • 定位改动 新增加了一个更加灵活的后台定位功能,可以随时开启或者关闭后台定位。首先记得在工程中的info配置文件,添加Required background modes,并增加App registers for location updates属性。
// 1. 实例化定位管理器
_locationManager = [[CLLocationManager alloc] init];
// 2. 设置代理
_locationManager.delegate = self;
// 3. 定位精度
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
// 4.请求用户权限:分为:⓵只在前台开启定位⓶在后台也可定位,
//注意:建议只请求⓵和⓶中的一个,如果两个权限都需要,只请求⓶即可,
//⓵⓶这样的顺序,将导致bug:第一次启动程序后,系统将只请求⓵的权限,⓶的权限系统不会请求,只会在下一次启动应用时请求⓵
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) {
//[_locationManager requestWhenInUseAuthorization];//⓵只在前台开启定位
[_locationManager requestAlwaysAuthorization];//⓶在后台也可定位
}
// 5.iOS9新特性:将允许出现这种场景:同一app中多个location manager:一些只能在前台定位,另一些可在后台定位(并可随时禁止其后台定位)。
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
_locationManager.allowsBackgroundLocationUpdates = YES;
}
// 6. 更新用户位置
[_locationManager startUpdatingLocation];

备注:在定位的时候,iOS系统定位的是国际坐标(地址坐标),如果要换成国内地图的话,需要转成国内坐标(火星坐标)。当然如果想要获得更好的地图定位体验,仍然需要第三方地图的纠偏与矫正。

//转GCJ-02
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc;

这儿有这些Demo的源码:iOS9新特性Demo


Xcode7

  • Crash Logs 对App Store上的程序或者TestFlight产生的Crash,会自动同步到Xcode7点击可以进行代码的修复。
  • Address Sanitizer 出现Crash时,精准定位到代码的某一行.这儿有一篇文章写得比较详细,值得好好研读一下。
  • Energy Gauge 协助诊断大量耗电的根源所在
  • 账号系统更新 xcode7可以用免费证书调试了,只需要一个App ID就可以自己创建证书用于开发调试,不过要上架的话还是要交“保护费”的。 同时iOS与OS X的账号合并,不需要两个账号了。

UI测试

Xcode自带XCUITest,onevcat有一篇文章讲得比较详细Xcode 7 UI 测试初窥


Objective-C新特性

  • Nullability
    其类似于Swift里面的!?语法糖,关键字为nullablenonnull__nullablenull_resettable

    + (nullable NSString *)friendWithName:(nonnull NSString *)name;
    - (void)startWithCompletionBlock:(nullable void (^)(NSError * __nullable error));
    @property (null_resettable, nonatomic, strong) UIView *view;
    

    也可以使用宏NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END来对整段代码进行检查。

  • Lightweight Generics

Object-C终于迎来了泛型了

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

以及自定义泛型关键字objecttype

@interface Stack<objecttype> : NSObject
- (void)pushObject:(ObjectType)object;
- (ObjectType)popObject;

@property (nonatomic, readonly) NSArray<objecttype> *allObjects;
@end</objecttype></objecttype>

__covariant - 协变性,子类型可以强转到父类型(里氏替换原则)
__contravariant - 逆变性,父类型可以强转到子类型

  • __kindof

__kindof用于标记为某种类型,避免不必要的警告。
例如- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;,里面不需要把子类进行一次强转了。


Swift2.0

  • Swift集成至iOS9系统中,占用8M空间

记得我在之前的企业如何开发优秀的App里面有说到减少安装包,里面说到在Swift与Object-C混用时,会增加安装包的大小,现在Swift2.0已经被集成到iOS系统里面去了,这也是一个不错的福音,看来一些重量级的App对于Swift的支持会从iOS9后全面介入。

  • 引入guard关键字,以及异常处理等

guard语句和if语句有点类似,都是根据其关键字之后的表达式的布尔值决定下一步执行什么。但与if语句不同的是,guard语句只会有一个代码块,不像if语句可以if else多个代码块。

guard let id = person["id"] else {
        print("没有身份证,不能进入考场!")
        return
    }
  • defer关键字
    defer的意思是在函数或者{...}语句块里面延迟执行,也就是等其它语句都执行完再执行defer里面的内容。

    func branch() -> String {
    var str = ""
    str += "1"
    defer { str += "2" }
    let counter = 3;
    
    if counter > 0 {
        str += "3"
        defer { str += "4" }
        str += "5"   
    }
    str += "6"
    return str
    }
    
  • #available 标注来进行多版本兼容
    例如下面的语句#available(iOS 8.0, *)是指8.0或者以上的版本

    if #available(iOS 8.0, *) {
    let alert = UIAlertController(title: "test", message: "app", preferredStyle: .Alert) UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
    } else {
    let alert = UIAlertView(title: "test", message: "app", delegate: nil, cancelButtonTitle: "ok")
    alert.show()
    }
    
  • repeat-while循环
    repeat-while取代了之前的do-while,使用do-while时会编译不通过。

    repeat {
    print(counter)
    counter--
    } while counter > 0
    
  • println统一为print
    除此之外,还有很多其它的小的改动。例数组contains、以及异常处理的关键字throwsthrow

    func requestImage(urlString:String) throws -> UIImage? {
    if let url = NSURL(string: urlString) {
        if let data = NSData(contentsOfURL: url) {
            return UIImage(data: data)
        } else {
            throw RequestImageError.NetworkError   
        }
    } else {
        throw RequestImageError.URLError   
    }
    }
    

WatchOS2

笔者暂时没有做过Watch App的开发,下面内容先记录一下,后续有用到的时候再研究一下。
1、从单纯的界面显示器变为可执行开发者代码的设备
2、可以在extension中访问到数字表冠和心跳计数
3、添加WatchConnectivity新框架和iPhone进行通讯
3、支持音视频播放和录音


总结

其实iOS9的新特性真的远不止这些,例如iOS9 Samper中的Demo里面有CoreImage的更新、wallet支付功能,MapKit通讯录等等。

参考阅读

2015-09-28 11:02232