65

最近,我一直在做一个简单的 iOS 8 分享扩展来了解系统是如何工作的。正如 Apple 在其App Extension Programming Guide中所述:

默认情况下,您的包含应用程序及其扩展无法直接访问彼此的容器。

这意味着扩展程序和包含的应用程序不共享数据。但在同一页面中,Apple 带来了一个解决方案:

如果您希望包含应用程序及其扩展能够共享数据,请使用 Xcode 或开发人员门户为应用程序及其扩展启用应用程序组。接下来,在门户中注册应用程序组并指定要在包含应用程序中使用的应用程序组。

然后可以使用 NSUserDefaults 在包含的应用程序和扩展程序之间共享数据。这正是我想做的。但由于某种原因,它不起作用。

在同一页面中,Apple 建议使用标准默认值:

var defaults = NSUserDefaults.standardUserDefaults()

在 WWDC 演示文稿 (217) 中,他们提出了一个通用包:

var defaults = NSUserDefaults(suiteName: kDefaultsPackage)

此外,我为包含应用程序目标和扩展目标启用了应用程序组,具有相同的应用程序组名称: XCode 目标功能、应用程序组

但所有这些设置都是徒劳的。我无法从扩展中检索存储在包含应用程序中的数据。就像两个目标使用完全不同的 NSUserDefaults 存储一样。

所以,

  1. 这种方法有解决方案吗?
  2. 如何在包含应用程序和共享扩展程序之间共享简单数据?数据只是 API 的用户凭据。
4

8 回答 8

50

您应该像这样使用 NSUserDefaults:

保存数据:

对象

NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.yougroup"];
[shared setObject:object forKey:@"yourkey"];
[shared synchronize];

迅速

let defaults = UserDefaults(suiteName: "group.yourgroup")
defaults?.set(5.9, forKey: "yourKey")

读取数据:

对象

NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.yougroup"];
id value = [shared valueForKey:@"yourkey"];
NSLog(@"%@",value);

迅速

let defaults = UserDefaults(suiteName: "group.yourgroup")
let x = defaults?.double(forKey: "yourKey")
print(x)

这会很好用!

于 2014-06-18T06:01:28.780 回答
15

这是我的做法:

  1. 打开您的主应用程序目标 > 功能 > 应用程序组设置为 on
  2. 添加一个新的应用程序组并确保它被勾选(例如 group.com.seligmanventures.LightAlarmFree)
  3. 打开您的监视目标(具有“功能”选项卡的那个)>“应用程序组”设置为开启
  4. 添加一个新的应用程序组并确保它被勾选(例如 group.com.seligmanventures.LightAlarmFree - 但必须与上述组同名)
  5. 将数据保存到组中,如下所示:

    var defaults = NSUserDefaults(suiteName: "group.com.seligmanventures.LightAlarmFree")
    defaults?.setObject("It worked!", forKey: "alarmTime")
    defaults?.synchronize()
    
  6. 从组中检索数据,如下所示:

    var defaults = NSUserDefaults(suiteName: "group.com.seligmanventures.LightAlarmFree") 
    defaults?.synchronize()
    
    // Check for null value before setting
    if let restoredValue = defaults!.stringForKey("alarmTime") {
        myLabel.setText(restoredValue)
    }
    else {
        myLabel.setText("Cannot find value")
    }
    
于 2015-08-10T19:47:27.070 回答
7

如果你有

group.yourappgroup

利用

var defaults = NSUserDefaults(suiteName: "yourappgroup")

这对我有用

于 2014-08-01T12:04:55.997 回答
5

所以显然它有效,只有当组名用作NSUserDefaults的套件名称时。

文档说 NSUserDefaults.standartUserDefaults() 也应该工作,但它没有,这可能是一个错误。

于 2014-06-09T13:07:09.933 回答
3

在我的场景中,我在父 iOS 应用程序和 WatchKit 之间共享数据。我正在使用 Xcode 6.3.1,iOS 部署目标 8.3

var defaults = NSUserDefaults(suiteName: "group.yourappgroup.example")

在您的 viewDidLoad 中确保您同步:

    override func viewDidLoad() {
    super.viewDidLoad()

    defaults?.synchronize()

}

按钮发送文本的示例,但当然您可以传递任何内容:

 @IBAction func btnSend(sender: UIButton) {
    var aNumber : Int = 0;
    aNumber = aNumber + 1

    //Pass anything with this line
    defaults?.setObject("\(aNumber)", forKey: "userKey")
    defaults?.synchronize()

}

然后在另一边确保应用组匹配:

 var defaults = NSUserDefaults(suiteName: "group.yourappgroup.example")

然后同步和校准:(在这种情况下“lblNumber”是一个 IBOutlet 标签)

defaults?.synchronize()
var tempVar = defaults!.stringForKey("userKey")!;
lblNumber.setText(tempVar);

然后,如果您想在这一侧设置一些内容并将其同步回来,那么只需执行相同的操作并进行同步,并确保您在另一侧调用的 stringForKey 是相同的:

defaults?.setObject("sending sample text", forKey: "sampleKey")
defaults?.synchronize()

希望这是有道理的

于 2015-05-10T01:09:03.887 回答
2

我翻译了 swift foogry 的答案,它有效!

保存数据:

let shared = NSUserDefaults(suiteName: "nameOfCreatedGroup")
shared("Saved String 1", forKey: "Key1")
shared("Saved String 2", forKey: "Key2")

读取数据:

let shared = NSUserDefaults(suiteName: "nameOfCreatedGroup")!
valueToRead1 = shared("Key1") as? String
valueToRead2 = shared("Key2") as? String
println(valueToRead1)   // Saved String 1
println(valueToRead2)   // Saved String 2
于 2015-05-11T11:19:28.940 回答
2

您可以通过以下步骤共享数据:

1)选择您的项目->选择功能选项卡->启用应用程序组->单击“+”->在“组”之后粘贴您的捆绑包ID。

在项目功能选项卡中启用 AppGroups

2)选择您的扩展 -> 选择功能选项卡 -> 启用应用程序组 -> 单击“+” -> 在“组”之后粘贴您的包 ID。

在扩展功能选项卡中启用 AppGroups

3)将以下代码放在您要共享的数据的主应用程序中:

NSUserDefaults * appGroupData = [[NSUserDefaults alloc]initWithSuiteName:@"group.com.appname"];
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:[self allData]]; // Get my array which I need to share
[appGroupData setObject:data forKey:@"Data"];
[appGroupData synchronize];

4)您可能会在扩展中获得对象:

NSUserDefaults * appGroupData = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.appname"];
NSData * data = [appGroupData dataForKey:@"Data"];
NSArray * arrReceivedData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
于 2018-12-14T11:31:22.317 回答
0

您应该像下面这样使用 NSUserDefaults,并确保您必须在您的临时配置文件中启用应用程序组,并且应用程序组必须配置为绿色符号,并且它应该添加到您的临时配置文件和 BundleID。

NSUserDefaults *sharedUserDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.yougroup"];
[sharedUserDefault setObject:object forKey:@"yourkey"];
[sharedUserDefault synchronize];

NSUserDefaults *sharedUserDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.yougroup"];
sharedUserDefault value = [sharedUserDefault valueForKey:@"yourkey"];
于 2015-10-12T12:41:23.530 回答