我刚安装了Xcode的最新测试版,尝试 Swift 2 以及Apple Watch开发部分的改进。
我实际上很难弄清楚为什么在 iOS 和观看OS2 之间分享信息的基本NSUserDefaults
方法不是'工作。
我跟着this step-by-step tutorial检查我是否错过了过程中的某些内容,比如为手机应用程序和扩展程序启用了相同的组,但这是我得到的内容: NOTHING < /强>
这是我在iPhone应用程序中为ViewController编写的内容:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var lb_testo: UITextField!
let shared_defaults:NSUserDefaults = NSUserDefaults(suiteName: "group.saracanducci.test")!
var name_data:NSString? = ""
override func viewDidLoad() {
super.viewDidLoad()
name_data = shared_defaults.stringForKey("shared")
lb_testo.text = name_data as? String
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func upgrade_name(sender: AnyObject) {
name_data = lb_testo.text
shared_defaults.setObject(name_data, forKey: "shared")
lb_testo.resignFirstResponder()
shared_defaults.synchronize()
}
}
以下是我在WatchKit的InterfaceController中所拥有的内容:
import WatchKit
import Foundation
class InterfaceController: WKInterfaceController {
@IBOutlet var lb_nome: WKInterfaceLabel!
let shared_defaults:NSUserDefaults = NSUserDefaults(suiteName: "group.saracanducci.test")!
var name_data:NSString? = ""
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
}
override func willActivate() {
super.willActivate()
if (shared_defaults.stringForKey("shared") != ""){
name_data = shared_defaults.stringForKey("shared")
lb_nome.setText(name_data as? String)
}else{
lb_nome.setText("No Value")
}
}
override func didDeactivate() {
super.didDeactivate()
}
}
我做了一些测试,似乎iOS应用程序和Watch OS可以利用不同的群体...... 他们不共享信息,他们将它们存储在本地。
有人有同样的问题吗?知道怎么解决吗?
答案 0 :(得分:41)
使用手表OS2,您无法再使用共享组容器。 Apple Docs:
使用共享组观看与其iOS应用共享数据的应用 必须重新设计容器以不同方式处理数据。在watchOS 2中, 每个进程必须管理自己在本地的任何共享数据的副本 容器目录。对于实际共享和更新的数据 这两个应用程序,这需要使用Watch Connectivity框架 在他们之间移动数据。
答案 1 :(得分:18)
NSUserDefaults(即使是应用程序组)也不会在watchOS 2中的iPhone和Watch之间进行同步。如果您要同步iPhone应用程序或Settings-Watch.bundle中的设置,则必须处理自己同步。
我发现在这种情况下使用WatchConnectivity的用户信息传输效果非常好。 您将在下面找到一个如何实现此功能的示例。该代码仅处理从手机到Watch的单向同步,但另一种方式也是如此。
在 iPhone应用中:
1)准备需要同步的设置字典
- (NSDictionary *)exportedSettingsForWatchApp
{
NSUserDefaults *userDefaults = [self userDefaults]; // the user defaults to sync
NSSet *keys = [self userDefaultKeysForWatchApp]; // set of keys that need to be synced
NSMutableDictionary *exportedSettings = [[NSMutableDictionary alloc] initWithCapacity:keys.count];
for (NSString *key in keys) {
id object = [userDefaults objectForKey:key];
if (object != nil) {
[exportedSettings setObject:object forKey:key];
}
}
return [exportedSettings copy];
}
2)确定何时需要将设置推到手表上 (此处未显示)
3)将设置按下至Watch
- (void)pushSettingsToWatchApp
{
// Cancel current transfer
[self.outstandingSettingsTransfer cancel];
self.outstandingSettingsTransfer = nil;
// Cancel outstanding transfers that might have been started before the app was launched
for (WCSessionUserInfoTransfer *userInfoTransfer in self.session.outstandingUserInfoTransfers) {
BOOL isSettingsTransfer = ([userInfoTransfer.userInfo objectForKey:@"settings"] != nil);
if (isSettingsTransfer) {
[userInfoTransfer cancel];
}
}
// Mark the Watch as requiring an update
self.watchAppHasSettings = NO;
// Only start a transfer when the watch app is installed
if (self.session.isWatchAppInstalled) {
NSDictionary *exportedSettings = [self exportedSettingsForWatchApp];
if (exportedSettings == nil) {
exportedSettings = @{ };
}
NSDictionary *userInfo = @{ @"settings": exportedSettings };
self.outstandingSettingsTransfer = [self.session transferUserInfo:userInfo];
}
}
在观看分机中:
4)接收用户信息传输
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *, id> *)userInfo
{
NSDictionary *settings = [userInfo objectForKey:@"settings"];
if (settings != nil) {
// Import the settings
[self importSettingsFromCompanionApp:settings];
}
}
5)将收到的设置保存到Watch
上的用户默认值- (void)importSettingsFromCompanionApp:(NSDictionary *)settings
{
NSUserDefaults *userDefaults = [self userDefaults]; // the user defaults to sync
NSSet *keys = [self userDefaultKeysForWatchApp]; // set of keys that need to be synced
for (NSString *key in keys) {
id object = [settings objectForKey:key];
if (object != nil) {
[userDefaults setObject:object forKey:key];
} else {
[userDefaults removeObjectForKey:key];
}
}
[userDefaults synchronize];
}
答案 2 :(得分:12)
Theres是一种重现旧功能的简单方法,我将旧组用户默认值导出到字典中,通过WatchConnectivity框架发送,然后将它们重新导入到另一端的用户默认值中:
在手机和观看应用中:
#import <WatchConnectivity/WatchConnectivity.h>
并声明为WCSessionDelegate
在应用启动后添加代码以启动会话:
if ([WCSession isSupported]) {
WCSession* session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
使用此功能将更新的默认值发送到其他设备(在当前[defaults synchronize]
之后调用):
[[WCSession defaultSession] updateApplicationContext:[[[NSUserDefaults alloc] initWithSuiteName:@"group.com.company.myapp"] dictionaryRepresentation] error:nil];
接收并将设置保存回默认设置 - 将其添加到WCDelegate:
-(void)session:(WCSession *)session didReceiveApplicationContext:(NSDictionary<NSString *,id> *)applicationContext {
NSLog(@"New Session Context: %@", applicationContext);
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.company.myapp"];
for (NSString *key in applicationContext.allKeys) {
[defaults setObject:[applicationContext objectForKey:key] forKey:key];
}
[defaults synchronize];
}
小心保持对非WC设备的支持 - 使用if ([WCSession isSupported])
答案 3 :(得分:7)
如上所述,共享的NSUserDefaults不再适用于WatchOS2。
这是@ RichAble的答案的快速版本,还有一些注释。
在您的iPhone应用中,请按以下步骤操作:
选择要将数据推送到Apple Watch的视图控制器,并在顶部添加框架。
import WatchConnectivity
现在,与手表建立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和其他手表套件应用类型),您可以添加框架:
import WatchConnectivity
然后设置连接会话:
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
})
}
}
这就是它的全部。
注意事项:
答案 4 :(得分:1)
我花了好几个小时才得到这个。观看这个非常有用的视频!它为您提供了如何使用WatchConnectivity在iPhone应用程序和wacth之间共享NSUserDefault的基本概念!