WatchConnectivity:学习 WCSession

作者:Natasha The Robot,原文链接,原文日期:2015-09-21
译者:小袋子;校对:numbbbbb;定稿:千叶知风

在读这篇文章之前,请检查一下你是否已经学习了之前两篇关于WatchOS 2的文章:

WCSession就是WatchConnectivity的魔力源泉,所以让我们赶紧深挖它吧!

WCSession.defaultSession()会返回WCSession的单例,用于在 iOS 和 Watch 应用之间传输数据。但是,在使用WCSession时仍有一些值得注意的地方。

首先,你必须给session设置一个delegate并启动它。

“默认的session用于两个对应应用的通信(例如 iOS 应用和它的原生 WatchKit 扩展)。这个session提供发送、接收和追踪状态的方法。

启动一个应用时,应该在默认的session上设置一个delegate并启动它。这将允许系统填充状态属性和提供任何优秀的背景传输。”—— Apple 文档说明。

所以你的代码应该写成这样:

let session = WCSession.defaultSession()
session.delegate = self
session.activateSession()

在这里,我推荐将你的WCSession作为一个单例,这样就可以在应用中随意使用它:

import WatchConnectivity

// Note that the WCSessionDelegate must be an NSObject 
// So no, you cannot use the nice Swift struct here!
class WatchSessionManager: NSObject, WCSessionDelegate {
    
    // Instantiate the Singleton
    static let sharedManager = WatchSessionManager()
    private override init() {
        super.init()
    }
    
    // Keep a reference for the session, 
    // which will be used later for sending / receiving data
    private let session = WCSession.defaultSession()
    
    // Activate Session
    // This needs to be called to activate the session before first use!
    func startSession() {
        session.delegate = self
        session.activateSession()
    }
}

现在你可以在AppDelegateapplication:didFinishLaunchingWithOptions方法中启动你的session,并且可以在应用的任意位置使用:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    // truncated...

    func application(application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
    {
        
        // Set up and activate your session early here!
        WatchSessionManager.sharedManager.startSession()
        
        return true
    }
    
    // truncated...
        
}

但是启动session是远远不够的。你需要通过WCSession的多重检查,这样你的应用就不需要做额外的格式化传输数据工作。

检查设备是否支持

检查 iOS 设备是否支持 session,WatchOS 也是支持 session 的。

如果你有一个通用应用,那就需要注意,例如iPad 不支持WCSession(因为 iPad 不能和 Watch 配对)。因此确保在 iOS 项目中做isSupported()检查:

if WCSession.isSupported() {
    let session = WCSession.defaultSession()
    session.delegate = self
    session.activateSession()
}

这意味着你的WatchSessionManager单例需要适应不支持WCSession的场景(使用可选值):

// Modification to the WatchSessionManager in the iOS app only
class WatchSessionManager: NSObject, WCSessionDelegate {
    
    // truncated ... see above section
    
    // the session is now an optional, since it might not be supported
    private let session: WCSession? = WCSession.isSupported() ? WCSession.defaultSession() : nil
    
    // starting a session has to now deal with it being an optional
    func startSession() {
        session?.delegate = self
        session?.activateSession()
    }

Watch 相关的 iOS App 状态

如果你从 iOS 应用发送数据到 Watch,你需要做一些额外的检查,这样当 Watch 处于无法接受数据的状态时,你就不会浪费 CPU 资源去处理用于传输的数据。

是否配对

显然,为了从 iOS 设备传输数据到 Watch,用户必须有一个 Watch 并且和 iOS 设备配对。

是否安装 Watch 应用

一个用户可能有一对设备,当然可以选择删除手表中的应用,所以为了数据传输,你需要检查你的应用确实有安装在所配对的 Apple Watch 上面。

如果用户有一对设备但是没有对应的应用,那你就可以在合适的时机向用户推荐你的应用,他很可能会安装你的应用。

为了让这些检查更加简单,并且能够在应用中随意使用,我喜欢在 iOS 应用中创建一个validSession变量:

// Modification to the WatchSessionManager in the iOS app only
class WatchSessionManager: NSObject, WCSessionDelegate {
    
    // truncated... see above
    
    private let session: WCSession? = WCSession.isSupported() ? WCSession.defaultSession() : nil
    
    // Add a validSession variable to check that the Watch is paired
    // and the Watch App installed to prevent extra computation 
    // if these conditions are not met.
     
    // This is a computed property, since the user can pair their device and / or
    // install your app while using your iOS app, so this can become valid  
    
    private var validSession: WCSession? {
       
        // paired - the user has to have their device paired to the watch
        // watchAppInstalled - the user must have your watch app installed
        
        // Note: if the device is paired, but your watch app is not installed
        // consider prompting the user to install it for a better experience
        
        if let session = session where session.paired && session.watchAppInstalled {
            return session
        }
        return nil
    }

    // truncated... see above
}

并发是否可用

最后,如果你在应用中有使用并发,你必须检查并发是否可用。我不会在WatchConnectivity教程中介绍过多并发的细节,但是如果你想要知道更多,可以观看超级有用和全面的 WWDC 2015 Creating Complications with ClockKit session

sessionWatchStateDidChange

注意,如果你的 iOS 应用需要WCSession状态变化的信息,这里有一个 delegate 方法,专门用于通知WCSession的状态变化:

/** Called when any of the Watch state properties change */
    func sessionWatchStateDidChange(session: WCSession) {
        // handle state change here
    }

例如,如果你的应用需要安装 Watch 应用,可以实现这个delegate方法,然后去检测你的 Watch 应用是否真正安装了,并且让用户在 iOS 应用中进行设置。

检查设备可达状态

为了正确在 iOS 和 Watch 中使用Interactive Messaging传输数据,你需要做一些额外的工作以确保两个应用处于可达状态:

Watch 应用的可达状态需要所配对的 iOS 设备在重启后至少解锁一次。这个属性能够用于决定 iOS 设备是否需要被解锁。如果reachable设为NO,可能是由于设备重启过,需要解锁。如果处于这种状态,Watch 将会展示一个提示框建议用户去解锁他们配对的 iOS 设备。

在使用Interactive Messaging时,我喜欢给我的单例增加一个额外的valideReachableSession变量:

// MARK: Interactive Messaging
extension WatchSessionManager {
    
    // Live messaging! App has to be reachable
    private var validReachableSession: WCSession? {
        // check for validSession on iOS only (see above)
        // in your Watch App, you can just do an if session.reachable check
        if let session = validSession where session.reachable {
            return session
        }
        return nil
    }

如果session是不可达的,你可以如 Apple 所建议的那样,提示用户去解锁他们的 iOS 设备。为了获知用户解锁设备,实现sessionReachabilityDidChangedelegate方法:

func sessionReachabilityDidChange(session: WCSession) {
    // handle session reachability change
    if session.reachable {
        // great! continue on with Interactive Messaging
    } else {
        // 😥 prompt the user to unlock their iOS device
    }
}

以上!现在你应该已经知道了WCSession的一些要领,所以我们将会学习更加好玩的部分 —— 真正使用它在 iOS 和 Watch 之间接收和发送收据!

你可以在 GitHub 查看完整的WatchSessionManager单例

本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问 http://swift.gg

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,024评论 4 62
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,599评论 18 139
  • 前言:其实,是想跳出总是吐槽高冷这个观点,去简单看吐槽高冷的这个行为。我写的文,总是希望从不同角度去看那些总是被“...
    一只不爱爬树的考拉阅读 706评论 3 0
  • 四月青阅读 431评论 11 15
  • 看到了一个家教工作,每天三小时,一个月800.自己胆小,找室友一同去,舍友没时间。找一个朋友,她说了一句:当保姆?...
    晨曦微微阅读 117评论 0 0