将数据传递给Apple Watch应用程序
我试图从我的应用程序传入数据到我的Apple Watch应用程序。 基本上,我使用的方法与创build当前小部件的方法相同,所以我通过NSUserDefaults传递数据。
问题是,当我运行我的应用程序时,数据不会像我所期望的那样更新Watch应用程序中的标签。
这是我有…
override init(context: AnyObject?) { // Initialize variables here. super.init(context: context) // Configure interface objects here. NSLog("%@ init", self) var defaults = NSUserDefaults(suiteName: "group.AffordIt") var totalBudgetCalculation = "" if (defaults!.stringForKey("totalBudgetWidget") != nil) { println("Worked") totalBudgetCalculation = defaults!.stringForKey("totalBudgetWidget")! initialBudgetLabel.setText("Initial: \(totalBudgetCalculation)") } var currentBudgetCalculation = "" if (defaults!.stringForKey("currentBudgetWidget") != nil) { currentBudgetCalculation = defaults!.stringForKey("currentBudgetWidget")! currentBudgetLabel.setText("Current: \(currentBudgetCalculation)") } }
我试着把这个代码放在willActivate()
,但是这似乎没有什么区别。
任何人都知道我要去哪里错了?
我用你的方法得到了它的工作。 我想有几件事你可以检查:
1)在设置值之后是否同步默认值:
defaults?.synchronize(); NSLog("%@ ", defaults?.dictionaryRepresentation())
2)您是否在应用程序和扩展中启用了应用程序组?
3)构buildNSDefaults时是否使用了正确命名的应用程序组? 例如,我使用:
NSUserDefaults(suiteName: "group.com.brindysoft.MyWatch");
一旦完成所有设置,我运行应用程序,设置默认值,然后运行扫描目标,从默认值读取值,似乎工作!
- 仍然卡住? 检查你的苹果帐户中的应用程序组
接受的答案适用于苹果手表操作系统1.请参阅NSUserDefaults不能在Watch OS2的Xcodetesting版上工作
对于OS2 – 您将需要使用WatchConnectivity框架并实现WCSessionDelegate。
import WatchConnectivity import WatchKit @available(iOS 9.0, *) var alertDelegate:HomeIC? = nil public class WatchData: NSObject,WCSessionDelegate { var session = WCSession.defaultSession() // class var shared: WatchData { struct Static { static var onceToken: dispatch_once_t = 0 static var instance: WatchData? = nil } dispatch_once(&Static.onceToken) { Static.instance = WatchData() } return Static.instance! } public func session(session: WCSession, didReceiveFile file: WCSessionFile){ print(__FUNCTION__) print(session) } public func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) { print(__FUNCTION__) print(session) alertDelegate?.showMessage("didReceiveApplicationContext") } public func sessionReachabilityDidChange(session: WCSession){ print(__FUNCTION__) print(session) print("reachability changed:\(session.reachable)") let text = session.reachable ? "reachable" : "unreachable" alertDelegate?.showMessage(text) } public func sessionWatchStateDidChange(session: WCSession) { print(__FUNCTION__) print(session) print("reachable:\(session.reachable)") // alertDelegate?.showMessage("sessionWatchStateDidChange") if !session.receivedApplicationContext.keys.isEmpty { alertDelegate?.showMessage(session.receivedApplicationContext.description) } } public func session(session: WCSession, didReceiveMessageData messageData: NSData){ if !session.receivedApplicationContext.keys.isEmpty { alertDelegate?.showMessage(session.receivedApplicationContext.description) } } public func session(session: WCSession, didReceiveMessage message: [String : AnyObject]){ print(__FUNCTION__) if let data = message["data"] { alertDelegate?.showMessage(data as! String) return } } public func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { print(__FUNCTION__) if let data = message["data"] { alertDelegate?.showMessage(data as! String) return } guard message["request"] as? String == "showAlert" else {return} } public func activate(){ if WCSession.isSupported() { // it is supported session = WCSession.defaultSession() session.delegate = self session.activateSession() print("watch activating WCSession") } else { print("watch does not support WCSession") } if(!session.reachable){ print("not reachable") return }else{ print("watch is reachable") } } }
样例用法
class HomeIC: WKInterfaceController { // MARK: Properties override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) // Initialize the `WCSession`. WatchData.shared.activate() alertDelegate = self } internal func showMessage(msg:String){ let defaultAction = WKAlertAction(title: msg, style: WKAlertActionStyle.Default) { () -> Void in } let actions = [defaultAction] self.presentAlertControllerWithTitle( "Info", message: "", preferredStyle: WKAlertControllerStyle.Alert, actions: actions) } }
在我的iPhone代码/我可以在这里调用共享数据
if #available(iOS 9.0, *) { WatchData.shared.sendInbox() } else { // Fallback on earlier versions }
而在别的地方,我还有另外一个独立的单独的手表数据会话。
@available(iOS 9.0, *) public class WatchData: NSObject,WCSessionDelegate { var session = WCSession.defaultSession() var payload:String = "" class var shared: WatchData { struct Static { static var onceToken: dispatch_once_t = 0 static var instance: WatchData? = nil } dispatch_once(&Static.onceToken) { Static.instance = WatchData() } return Static.instance! } public func sessionReachabilityDidChange(session: WCSession){ print(__FUNCTION__) print(session) print("reachability changed:\(session.reachable)") if (session.reachable){ } } public func sessionWatchStateDidChange(session: WCSession) { print(__FUNCTION__) print(session) print("reachable:\(session.reachable)") } public func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { print(__FUNCTION__) guard message["request"] as? String == "showAlert" else {return} guard let m = message["m"] as? String else { return } print("msg:",m) } public func sendInbox(){ if (!session.reachable){ if WCSession.isSupported() { // it is supported session = WCSession.defaultSession() session.delegate = self session.activateSession() print("iphone activating WCSession") } else { print("iphone does not support WCSession") } session.activateSession() } if(session.paired){ if(session.watchAppInstalled){ print("paired | watchAppInstalled") } }else{ print("not paired | or no watchAppInstalled") } if(!session.reachable){ print("not reachable") return }else{ /*let transfer:WCSessionUserInfoTransfer = (session.transferUserInfo(["data" : "Test2"]) as WCSessionUserInfoTransfer?)! if(transfer.transferring){ print("-> iphone") }else{ print("!-> iphone") }*/ session.sendMessage(["data" :"test"], replyHandler: { reply in }, errorHandler: { error in print(error) }) } } }
请参阅示例手表os2应用程序
https://github.com/shu223/watchOS-2-Sampler/tree/20eeebeed66764d0814603e97d3aca5933236299
正如@johndpope所说,共享NSUserDefaults不再适用于WatchOS2。
我发布了一个简化的解决scheme,不像约翰那样function齐全,但在大多数情况下都能完成工作。
在你的iPhone App中 ,按照下列步骤操作:
selectfind您想要将数据推送到Apple Watch的视图控制器,然后在顶部添加框架。
import WatchConnectivity
现在,与手表build立WatchConnectivity会话并发送一些数据。
if WCSession.isSupported() { //makes sure it's not an iPad or iPod let watchSession = WCSession.defaultSession() watchSession.delegate = self watchSession.activateSession() if watchSession.paired && watchSession.watchAppInstalled { do { try watchSession.updateApplicationContext(["foo": "bar"]) } catch let error as NSError { print(error.description) } } }
请注意,如果你跳过设置委托,这将不起作用,所以即使你从不使用它,你必须设置它并添加这个扩展:
extension MyViewController: WCSessionDelegate { }
现在,在你的手表应用程序 (这个确切的代码适用于Glances和其他手表套件应用程序types以及),你添加框架:
import WatchConnectivity
然后你build立连接会话:
override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) let watchSession = WCSession.defaultSession() watchSession.delegate = self watchSession.activateSession() }
你只需要听取和处理来自iOS应用程序的消息:
extension InterfaceController: WCSessionDelegate { func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) { print("\(applicationContext)") dispatch_async(dispatch_get_main_queue(), { //update UI here }) } }
这里的所有都是它的。
注意事项:
- 您可以随时发送新的applicationContext,无论手表是在附近并连接还是在手表应用程序运行。 这将以智能的方式在后台传输数据,并且在手表应用程序启动时数据就在那里等待。
- 如果您的手表应用程序确实处于活动状态并正在运行,则应在大多数情况下立即收到该信息
- 您可以反转此代码,让手表以相同的方式将消息发送到iPhone应用程序。
- 您的手表应用程序在查看时收到的applicationContext将只是您发送的最后一条消息。 如果您在查看手表应用程序之前发送了20条消息,则会忽略前19条并处理第20条消息。
- 要在两个应用程序之间进行直接/硬连接,或进行后台文件传输或排队消息,请查看WWDCvideo 。
应用程序和手表之间的另一种沟通方式是通过虫洞:
https://github.com/mutualmobile/MMWormhole
发送:
[self.wormhole passMessageObject:@{@"titleString" : title} identifier:@"messageIdentifier"]; id messageObject = [self.wormhole messageWithIdentifier:@"messageIdentifier"];
收到:
[self.wormhole listenForMessageWithIdentifier:@"messageIdentifier" listener:^(id messageObject) { // Do Something }];