【问题标题】:WatchConnectivity, How to Share an Array between iPhone and Apple WatchWatchConnectivity,如何在 iPhone 和 Apple Watch 之间共享数组
【发布时间】:2017-10-19 00:42:25
【问题描述】:

我试图在 Swift 4 中的 iPhone 和 Apple Watch 应用程序之间传递一个数组,到目前为止我一直没有成功。以下是我尝试遵循的一些示例,但均未成功。在这些示例中,它们不包含许多功能,但是当我尝试像这样编写它时,它会给出错误does not conform to protocols,此外,当我声明监视会话时它没有正确声明,didRecieveApplicationContext 也是在 swift 4 中与其他问题/示例中显示的非常不同 Link Link2

这是我的 iPhone 视图控制器

import UIKit
import WatchConnectivity

class watchtimetablemaker: UIViewController, WCSessionDelegate {

func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}

func sessionDidBecomeInactive(_ session: WCSession) {
}

func sessionDidDeactivate(_ session: WCSession) {
}


var watchSession: WCSession?
var initalArray = [String]()
var combination = ""
var vdlArray = [String]()


@IBAction func Save(_ sender: Any) {

    vdlArray.removeAll()

//here I edit the arrays, add instances etc. cut out for fluency

    self.view.endEditing(true)

    sendToWatch()

    UserDefaults.standard.set(vdlArray, forKey: "vdlarray")
    UserDefaults.standard.synchronize()

    print(initalArray)
    print(vdlArray)

}

func sendToWatch(){
    do{
        let appDictionary = ["Array": initalArray]
        try WCSession.default.updateApplicationContext(appDictionary)
    }
    catch {
        print(error)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    if (WCSession.isSupported()){
        watchSession = WCSession.default
        watchSession?.delegate = self
        watchSession?.activate()
    }

    vdlArray = UserDefaults.standard.array(forKey: "vdlarray") as! [String]

    print(vdlArray)

}

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

这是 Apple Watch 控制器

import WatchKit
import Foundation
import WatchConnectivity


class TimetableWatch: WKInterfaceController, WCSessionDelegate {

func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
    load()
}

@IBOutlet var tabletitle: WKInterfaceTable!
var watchSession: WCSession?
var tableData = [String]()

override func awake(withContext context: Any?) {
    super.awake(withContext: context)

    if (WCSession.isSupported()){
        watchSession = WCSession.default
        watchSession?.delegate = self
        watchSession?.activate()
    }

    load()

    tabletitle.setNumberOfRows(tableData.count, withRowType: "Cell")

    var i = 0
    for item in tableData {
        let row = tabletitle.rowController(at: i) as! TableCellRow

        row.tbalecelllabel.setText(item)

        i = i + 1
    }
}

func load(){

    func session(session: WCSession, didRecieveApplicationContext applicationContext: [String : Any]) {

        DispatchQueue.main.async() { () -> Void in
            if let retreivedArray = applicationContext["Array"] as? [String] {
                self.tableData = retreivedArray
                print(self.tableData)
            }
        }
    }
}

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

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

我无法找到任何与 swift4 相关的文档,因此,我们将不胜感激。

【问题讨论】:

  • 我还没有使用过 Swift 4,但是你的 didReceiveApplicationContext 函数被包装在 load() 函数中看起来很奇怪。您可以像这样声明 WCSession:let session = WCSession.default()

标签: arrays watchkit swift4 watchconnectivity


【解决方案1】:

WKInterfaceController:

我同意 Jens Peter 的评论,即您不应该将 didReceiveApplicationContext 包装在 load() 函数中。

这样处理activationDidCompleteWith 中的错误:

func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
    if let error = error {
        print("Activation failed with error: \(error.localizedDescription)")
        return
    }
    print("Watch activated with state: \(activationState.rawValue)")
}

这也将有助于确定 WatchConnectivity 是否已经建立。

完全删除var watchSession: WCSession?,并在awake(withContext)中声明WCSession为:

if WCSession.isSupported() {
        let watchSession = WCSession.default
        watchSession = self
        watchSession()
    }

同时删除在awake(withContext) 中对load() 的调用。

InterfaceController 中,将一些print 语句放入您的WCSession 存根中会很有帮助,即使您没有完全使用它们。您可以查看 WatchConnectivity 是否正在激活。

func sessionDidBecomeInactive(_ session: WCSession) {
    // To support multiple watches.
    print("WC Session did become inactive.")
}

func sessionDidDeactivate(_ session: WCSession) {
    // To support multiple watches.
    WCSession.default.activate()
    print("WC Session did deactivate.")
}

func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
    if let error = error {
        print("WC Session activation failed with error: \(error.localizedDescription)")
        return
    }
    print("Phone activated with state: \(activationState.rawValue)")
}

正如您在sessionDidDeactivate 中看到的那样,这条线WCSession.default.activate() 将允许在用户碰巧拥有多只手表的情况下支持多只手表。

像在WKInterfaceController 中一样删除var watchSession: WCSession?。再次在viewDidLoad() 中检查WCSession 支持:

if WCSession.isSupported() {
        let watchSession = WCSession.default
        watchSession = self
        watchSession()
    }

sendToWatch() 更新为:

func sendToWatch() {
let session = WCSession.default()

if session.activationState == .activated {
    let appDictionary = ["Array": initalArray]
do { 
    try session.updateApplicationContext(appDictionary)
} catch {
    print(error)
  }
 }  
}

我认为这会稍微清理一下,并希望能奏效,或者至少让你前进。但是,我没有在项目中构建它。希望这可以帮助。

【讨论】:

    猜你喜欢
    • 2015-04-04
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多