2016年IOS新技术回顾

WWDC2016,Apple发布了ios10,每次版本发布,都会带来新的接口,新的机会,也能间接的看到Apple的未来发展方向。

这里就不讨论iphone7、MacBook Pro、Apple Watch、Apple TV以及AirPods了。

下面回顾一下,Apple今年为我们带来了什么

一,一些限制

IPV6

HTTPS

1.IPV6

由于IPv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍

6月1号以后提交新版本需要支持IPV6-Only的网络

与IPv4地址空间需要扩充迫在眉睫,越来越多的企业和移动电话运营商部署IPv6 DNS64和NAT64网络。DNS64 / NAT64网络是一种能使ipv6网络。取决于应用程序的性质,过渡有不同的含义:如果您正在编写一个客户端应用程序使用高级网络api,如NSURLSession和CFNetwork框架,你应该不需要改变任何东西为您的应用程序使用IPv6地址。如果项目中用了老的AFNetworking或ASIHTTPRequest等第三方网络请求框架则可能需要做一下适配。因为,苹果审核是不会让你过得。


ipv6.png

客户端向服务器端请求域名解析,首先通过DNS64 Server查询IPv6的地址,如果查询不到,再向DNS Server查询IPv4地址,通过DNS64 Server合成一个IPV6的地址,最终将一个IPV6的地址返回给客户端

关于IPV6的详细介绍请见:
IPV6

2.HTTPS
前面一个大神已经详细得介绍了HTTPS的相关知识,讲得非常详细,大家想看的话可以回顾一下。我在这也就不做过多赘述了。
HTTPS

  • 2017年1月1日起,苹果App Store中的所有App都必须启用 App Transport Security(ATS)安全功能。(但延期了)

"应用传输安全协议是与iOS9和OS X 10.11一同发布的,该协议需要应用程序通过HTTPS使用安全的网络连接,以提高用户的数据和隐私安全。
在2016年WWDC上我们宣布在今年年底之前,提交到App Store的应用程序必须支持应用传输安全协议。为了给你们充裕的时间去准备,这个截止日期已被延长,当新的截止日期确定的时候,我们将及时提供相关信息。"

  • App Transport Security(应用程序安全传输),简称 ATS,是苹果在 iOS 9 中首次推出的一项隐私安全保护功能,启用ATS后,它会屏蔽明文HTTP资源加载,强制App通过HTTPS连接网络服务,通过传输加密保障用户数据安全。
  • ATS要求服务器必须支持传输层安全(TLS)协议1.2以上版本;证书必须使用SHA256或更高的哈希算法签名;必须使用2048位以上RSA密钥或256位以上ECC算法等等,不满足条件的证书,ATS都会拒绝连接。强制开启ATS体现了苹果一贯的隐私保护态度。 开发者需要HTTPS证书。

二,ios10

IMessage

SiriKit

Speech Recognition

User Notifications

Others

1.IMessage
IMessage获得重大更新,提供消息气泡框效果,手写信息。同时内置的emoji表情也得到优化,除了图片变大3倍外,还能将文字直接转化成emoji表情。苹果还特别为IMessage开辟了应用专区,所以你也可以做IMessage App了。

使用Messages framework创建两种类型的app extensions:
Sticker packs
IMessage apps
第一种方式仅仅提供静态的贴纸,贴纸包图片,用户可以发送内联消息附加到消息气泡中。贴纸包不需要任何代码。你添加标签图像文件拖到贴纸包文件夹内的贴纸资源目录。有效的图像文件必须符合以下规格:

  • 图片必须是png、apng、gif、jpeg中的一种
  • 图片必须小于500k
  • 为了效果好,图像不应少于100×100pt,或超过206×206pt
    如果你想做这些事的时候你就要用到第二种方式了

Use iMessage apps to:

  • Present a custom user interface inside the Messages app; see MSMessagesAppViewController.
  • Create a custom or dynamic sticker browser; see MSStickerBrowserViewController.
  • Insert text, stickers, or media files into the Messages app’s input field; see MSConversation.
  • Create interactive messages that carry app-specific data; see MSMessage.
  • Update interactive messages (for example, to create games or collaborative apps); see MSSession.
//example1作为一个贴纸浏览器

class MessagesViewController: MSMessagesAppViewController, MSStickerBrowserViewDataSource {
var stickers = [MSSticker]()
func loadStickers() {
for i in 1...2 {
if let url = Bundle.main.url(forResource: "Sticker \(i)", withExtension: "png"){
 do {
    let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "")
    stickers.append(sticker)
    } catch {
    print(error)
    }
   }
 }
}
func createStickerBrowser() {
    let controller = MSStickerBrowserViewController(stickerSize: .large)
    
    addChildViewController(controller)
    view.addSubview(controller.view)
    
    controller.stickerBrowserView.backgroundColor = UIColor.purple
    controller.stickerBrowserView.dataSource = self
    
    view.topAnchor.constraint(equalTo: controller.view.topAnchor).isActive = true
    view.bottomAnchor.constraint(equalTo: controller.view.bottomAnchor).isActive = true
    view.leftAnchor.constraint(equalTo: controller.view.leftAnchor).isActive = true
    view.rightAnchor.constraint(equalTo: controller.view.rightAnchor).isActive = true
}

func numberOfStickers(in stickerBrowserView: MSStickerBrowserView) -> Int {
  return stickers.count
}

func stickerBrowserView(_ stickerBrowserView: MSStickerBrowserView, stickerAt index: Int) -> MSSticker {
  return stickers[index]
}

override func viewDidLoad() {
    super.viewDidLoad()
    loadStickers()
    createStickerBrowser()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

// MARK: - Conversation Handling
    override func willBecomeActive(with conversation: MSConversation) {
    }
    override func didResignActive(with conversation: MSConversation) {
    }
    override func didReceive(_ message: MSMessage, conversation: MSConversation) {
    }
    override func didStartSending(_ message: MSMessage, conversation: MSConversation) {
    }
    override func didCancelSending(_ message: MSMessage, conversation: MSConversation) {
    }
    override func willTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
    }
    override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
    }
}
example2(交互式)

class MessagesViewController: MSMessagesAppViewController {

@IBOutlet weak var stepper: UIStepper!

@IBAction func didPress(button sender: AnyObject) {
if let image = createImageForMessage(), let conversation = activeConversation {
    let layout = MSMessageTemplateLayout()
    layout.image = image
    layout.caption = "云莱坞"
    
    let message = MSMessage()
    message.layout = layout
    message.url = URL(string: "http://www.yunlaiwu.com/")
    
    conversation.insert(message, completionHandler: { (error) in
      print(error ?? "no error")
    })
   }
}

func createImageForMessage() -> UIImage? {
    let background = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
    background.backgroundColor = UIColor.white
    
    let label = UILabel(frame: CGRect(x: 75, y: 75, width: 150, height: 150))
    label.font = UIFont.systemFont(ofSize: 56.0)
    label.backgroundColor = UIColor.red
    label.textColor = UIColor.white
    label.text = "\(Int(stepper.value))"
    label.textAlignment = .center
    label.layer.cornerRadius = label.frame.size.width/2.0
    label.clipsToBounds = true
    
    let imageView = UIImageView(frame: CGRect(x: 0, y: 200, width: 300, height: 100))
    imageView.image = UIImage(named:"Sticker 2")
    background.addSubview(label)
    background.addSubview(imageView)
    
    background.frame.origin = CGPoint(x: view.frame.size.width, y: view.frame.size.height)
    view.addSubview(background)
    
    UIGraphicsBeginImageContextWithOptions(background.frame.size, false, UIScreen.main.scale)
    background.drawHierarchy(in: background.bounds, afterScreenUpdates: true)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    background.removeFromSuperview()
    
    return image
}

2.SiriKit
Apple 为我们开放了两个framework让我们更好的接入Siri
Intents、IntentsUI
Intents框架是必须支持的,支持基本应用程序和系统之间的通信。
IntentsUI框架是可选的,他提供了任务成功操作后的自定义UI接口。

它所包括的领域:

  • VoIP calling
  • Messaging
  • Payments
  • Photo
  • Workouts
  • Ride booking
  • CarPlay (automotive vendors only)
  • Restaurant reservations (requires additional support from Apple)

接入siri的注意事项:

  • 证书支持
  • plist文件支持你所要的操作事件


    siri.png
import Intents

// As an example, this class is set up to handle Message intents.
// You will want to replace this or add other intents as appropriate.
// The intents you wish to handle must be declared in the extension's Info.plist.

// You can test your example integration by saying things to Siri like:
// "Send a message using <myApp>"
// "<myApp> John saying hello"
// "Search for messages in <myApp>"

class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling {

override func handler(for intent: INIntent) -> Any {
    // This is the default implementation.  If you want different objects to handle different intents,
    // you can override this and return the handler you want for that particular intent.
    return self
}

// MARK: - INSendMessageIntentHandling

// Implement resolution methods to provide additional information about your intent (optional).
func resolveRecipients(forSendMessage intent: INSendMessageIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
    if let recipients = intent.recipients {
    
    // If no recipients were provided we'll need to prompt for a value.
    if recipients.count == 0 {
    completion([INPersonResolutionResult.needsValue()])
    return
}

var resolutionResults = [INPersonResolutionResult]()
for recipient in recipients {
    let matchingContacts = [recipient] // Implement your contact matching logic here to create an array of matching contacts
    switch matchingContacts.count {
    case 2  ... Int.max:
    // We need Siri's help to ask user to pick one from the matches.
    resolutionResults += [INPersonResolutionResult.disambiguation(with: matchingContacts)]
    
    case 1:
    // We have exactly one matching contact
    resolutionResults += [INPersonResolutionResult.success(with: recipient)]
    
    case 0:
    // We have no contacts matching the description provided
    resolutionResults += [INPersonResolutionResult.unsupported()]
    
    default:
    break
    
    }
}
    completion(resolutionResults)
    }
}

func resolveContent(forSendMessage intent: INSendMessageIntent, with completion: @escaping (INStringResolutionResult) -> Void) {
        if let text = intent.content, !text.isEmpty {
        completion(INStringResolutionResult.success(with: text))
    } else {
        completion(INStringResolutionResult.needsValue())
    }
}

// Once resolution is completed, perform validation on the intent and provide confirmation (optional).

func confirm(sendMessage intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) {
    // Verify user is authenticated and your app is ready to send a message.
    
    let userActivity = NSUserActivity(activityType: NSStringFromClass(INSendMessageIntent.self))
    let response = INSendMessageIntentResponse(code: .ready, userActivity: userActivity)
    completion(response)
}

// Handle the completed intent (required).

func handle(sendMessage intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) {
    // Implement your application logic to send a message here.
    
    let userActivity = NSUserActivity(activityType: NSStringFromClass(INSendMessageIntent.self))
    let response = INSendMessageIntentResponse(code: .success, userActivity: userActivity)
    completion(response)
}

// Implement handlers for each intent you wish to handle.  As an example for messages, you may wish to also handle searchForMessages and setMessageAttributes.

// MARK: - INSearchForMessagesIntentHandling

func handle(searchForMessages intent: INSearchForMessagesIntent, completion: @escaping (INSearchForMessagesIntentResponse) -> Void) {
    // Implement your application logic to find a message that matches the information in the intent.
    
    let userActivity = NSUserActivity(activityType: NSStringFromClass(INSearchForMessagesIntent.self))
    let response = INSearchForMessagesIntentResponse(code: .success, userActivity: userActivity)
    // Initialize with found message's attributes
    response.messages = [INMessage(
    identifier: "identifier",
    content: "I am so excited about SiriKit!",
    dateSent: Date(),
    sender: INPerson(personHandle: INPersonHandle(value: "sarah@example.com", type: .emailAddress), nameComponents: nil, displayName: "Sarah", image: nil,  contactIdentifier: nil, customIdentifier: nil),
    recipients: [INPerson(personHandle: INPersonHandle(value: "+1-415-555-5555", type: .phoneNumber), nameComponents: nil, displayName: "John", image: nil,  contactIdentifier: nil, customIdentifier: nil)]
    )]
    completion(response)
}

// MARK: - INSetMessageAttributeIntentHandling

func handle(setMessageAttribute intent: INSetMessageAttributeIntent, completion: @escaping (INSetMessageAttributeIntentResponse) -> Void) {
    // Implement your application logic to set the message attribute here.
    
    let userActivity = NSUserActivity(activityType: NSStringFromClass(INSetMessageAttributeIntent.self))
    let response = INSetMessageAttributeIntentResponse(code: .success, userActivity: userActivity)
    completion(response)
}
}

3.Speech Recognition

语音识别技术原理

iOS 10引入了一个新的API,支持连续语音识别,可以将识别语音转录成文本。可以执行语音实时转录和记录音频。

SpeechFramework框架中的重要类

SFSpeechRecognizer:这个类是语音识别的操作类,用于语音识别用户权限的申请,语言环境的设置,语音模式的设置以及向Apple服务发送语音识别的请求。
SFSpeechRecognitionTask:这个类是语音识别服务请求任务类,每一个语音识别请求都可以抽象为一个SFSpeechRecognitionTask实例,其中SFSpeechRecognitionTaskDelegate协议中约定了许多请求任务过程中的监听方法。
SFSpeechRecognitionRequest:语音识别请求类,需要通过其子类来进行实例化。
SFSpeechURLRecognitionRequest:通过音频URL来创建语音识别请求。
SFSpeechAudioBufferRecognitionRequest:通过音频流来创建语音识别请求。
SFSpeechRecognitionResult:语音识别请求结果类。
SFTranscription:语音转换后的信息类。

当然,首先为了安全你得到plist文件中加权限

SFSpeechRecognizer.requestAuthorization { authStatus in
    if authStatus == SFSpeechRecognizerAuthorizationStatus.authorized {
        if let path = Bundle.main.url(forResource: "PPAP", withExtension: ".mp3") {
            let recognizer = SFSpeechRecognizer()
                let request = SFSpeechURLRecognitionRequest(url: path)
                    recognizer?.recognitionTask(with: request, resultHandler: { (result, error) in
                if let error = error {
                   print("There was an error: \(error)")
                } else {
                   print(result?.bestTranscription.formattedString)
                }
            })
        }
    }
}

4.User Notifications
支持了很多用户定义的通知,并且可以捕捉到各个通知状态的回调。以往的通知是大家想接收的都提前做好准备,然后一下全量分发,没收到也不管了,也不关心发送者。现在用户通知做成了和网络请求有点像,一个request,response的流程,也支持了error处理,可以在各个状态的方法中做一些额外操作,并且也能取到一些字段,如发送者等。
更为重要的是,新增了UserNotificationsUI.framework框架,在收到通知的时候,可自定义通知UI样式

let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert,.badge,.sound]) { (granted, error) in
    if granted {
        print("授权成功")
    }else{
        print("授权失败")
    }
}

let content = UNMutableNotificationContent()
content.title = "云莱坞 PPAP"
content.body = "I have a pen I have an apple"
content.subtitle = "have a pineapple"
content.sound = UNNotificationSound.default()

let trigger1 = UNTimeIntervalNotificationTrigger(timeInterval: 61, repeats: true)

let request = UNNotificationRequest(identifier: "notificationTest", content: content, trigger:trigger1)

UNUserNotificationCenter.current().add(request) { (error) in
    if (error != nil) {
        print(error?.localizedDescription)
    }
}

5.Others

  • CallKit 集成了VoIP及信息标识,还有了黑名单功能,当然不是云莱坞的黑名单
//开始请求的方法,在打开设置-电话-来电阻止与身份识别开关时,系统自动调用
- (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context;
//添加黑名单:根据生产的模板,只需要修改CXCallDirectoryPhoneNumber数组,数组内号码要按升序排列
- (BOOL)addBlockingPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context;
// 添加信息标识:需要修改CXCallDirectoryPhoneNumber数组和对应的标识数组;CXCallDirectoryPhoneNumber数组存放的号码和标识数组存放的标识要一一对应,CXCallDirectoryPhoneNumber数组内的号码要按升序排列
- (BOOL)addIdentificationPhoneNumbersToContext:(CXCallDirectoryExtensionContext *)context;
  • Wide Color 宽域颜色
@available(iOS 10.0, *)
public init(displayP3Red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)
  • Adapting to the True Tone Display 真彩色显示

UIWhitePointAdaptivityStyle

共有五种选择:
UIWhitePointAdaptivityStyleStandard 标准
UIWhitePointAdaptivityStyleReading 阅读
UIWhitePointAdaptivityStylePhoto 图片
UIWhitePointAdaptivityStyleVideo 视频
UIWhitePointAdaptivityStyleGame 游戏

  • App Search Enhancements 应用搜索增强

  • Widget Enhancements 锁屏部件增强

  • News Publisher Enhancements 新闻出版商增强

  • Apple Pay Enhancements 支付增强

  • Security and Privacy Enhancements 安全和保密性增强

三,swift3.0

1.去除了swift2系列弃用得特性
2.语法精简,更加哲理性(这词用得好啊)
3.响应式,函数式,面向协议等语言现代化。

let queue = dispatch_queue_create("this is Swift 2.2", nil)
dispatch_async(queue) {
    print("Swift 2.2 queue")
}

Swift 3 取消了这种冗余的写法,而采用了更为面向对象的方式:

let queue = DispatchQueue(label: "this is Swift 3.0")
queue.async {
    print("Swift 3 queue")
}

当然,问题还很多,但4.0就快来了

四,watchOS3.0,tvOS,AppStore,macOS Sierra...

1.watchOS3.0

  • 新增智能回覆与 Scribble 功能,可在表面手写文字用以回覆讯息。
  • 新增 SOS 功能,其支持全球的语言与紧急电话,危急时刻可立即通话或发出讯息。
  • 新增的《Breathe》App 能提醒用户休息片刻、多做深呼吸。
  • 《活动记录》App 加入 Activity Sharing 功能,能将您个人的活动量分享给亲朋好友或健身教练,与他人运动竞争或帮助维持健康。《活动记录》更针对乘坐轮椅的残障用户优化设计,提醒何时该稍做休息。

2.tvOS

整合 Siri,用以加强语音搜索功能。此外,tvOS 将新增 Single Sign-on 功能,仅需登入一次即可浏览所有付费电视频道。
当然,国内是被墙的

3.AppStore
AppStore 2.0 变革:更改拆帐比例、置入搜索广告、缩短审查时间

4.macOS Sierra

  • 新增 Auto Unlock 功能,当用户戴着配对认证的 Apple Watch 开启 Mac 电脑立即自动登入,无须输入密码。
  • 新增 Universal Clipboard 功能,使用 iCloud 可跨苹果设备复制与贴上文字、照片、影片等。
  • 使用 iCloud Drive,将允许多部 Mac 电脑共用桌面,而且 iPhone、iPad 也能存取桌面上的档案。
  • 新增 Optimized Storage 功能,当 Mac 电脑容量不足,自动将不常用的档案上传 iCloud,提醒用户清空垃圾桶。
  • 线上付款将支持 Apple Pay,搭配 iPhone 或 Apple Watch 快速且安全地完成网购的付款动作。
  • 包括《地图》、《邮件》、《Pages》、《Numbers》、《Keynote》甚至第三方 Apps 将支持分页功能。
  • Safari 与 iTunes 新增 Picture in Picture 功能,以子母画面的方式观赏影片。
  • 加入 Siri 功能,可在 macOS Sierra 当中语音搜索讯息、文件、照片、网页等,甚至语音建立备忘录或开启 FaceTime 视讯。登陆 macOS Sierra 之后,Siri 终能跨苹果四大平台使用。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容