【问题标题】:Sharing data between an iOS 8 share extension and main app在 iOS 8 共享扩展程序和主应用程序之间共享数据
【发布时间】:2019-03-29 04:22:13
【问题描述】:

最近,我一直在制作一个简单的 iOS 8 共享扩展来了解系统的工作原理。正如苹果在其App Extension Programming Guide 中所说:

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

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

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

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

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

var defaults = NSUserDefaults.standardUserDefaults()

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

var defaults = NSUserDefaults(suiteName: kDefaultsPackage)

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

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

所以,

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

【问题讨论】:

标签: ios swift ios-app-extension userdefaults


【解决方案1】:

你应该像这样使用 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)

这会很好用!

【讨论】:

  • 询问了swift语言请使用或至少添加swift语言更新您的帖子
  • 很高兴看到目标 c 沿着 swift 旁边。它有助于理解差异。考虑到 ObjC 的大量代码示例,而目前 swift 的代码示例并不多,理解如何转换它是件好事。
  • 实际上在 Swift 中 .synchronize() 是多余的
【解决方案2】:

我是这样做的:

  1. 打开您的主应用目标 > 功能 > 应用组设置为开启
  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")
    }
    

【讨论】:

  • 你知道 defaults.suiteName 是否像 defaults.standard 一样被永久存储吗?
  • 语法更新 var defaults = UserDefaults(suiteName: "group.com.seligman") defaults?.set(sharedTxt, forKey: "shared")
【解决方案3】:

如果你有

group.yourappgroup

使用

var defaults = NSUserDefaults(suiteName: "yourappgroup")

这对我有用

【讨论】:

  • 我收到错误 Incorrect argument label in call (have 'suiteName:', expected 'user:')
  • 对,这对我不起作用。 Xcode 6 显示了相应的异常:Using your own bundle identifier as an NSUserDefaults suite name does not make sense and will not work. Break on _NSUserDefaults_Log_Nonsensical_Suites to find this。虽然可以使用前缀group.
  • @naturalc NSUserDefaults(suiteName:) 返回一个可选的 NSUserDefaults。您应该使用可选绑定来确保它有效。试着把!最后。
  • @Pops:这是NSUserDefaults 的 Swift 注释中的一个错误。实际上参数应该是可选的,而不是 init 本身。我已经举报了。
【解决方案4】:

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

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

【讨论】:

  • 您能否添加一些设置NSUserDefaults 和传递数据的示例代码。谢谢
  • 是否必须将组添加到两个目标?
【解决方案5】:

在我的场景中,我在父 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()

希望这是有道理的

【讨论】:

    【解决方案6】:

    我翻译了 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
    

    【讨论】:

      【解决方案7】:

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

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

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

      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];
      

      【讨论】:

      • 无法在“源代码标签”中放置代码,这就是答案没有以正确格式显示的原因
      【解决方案8】:

      您应该像下面这样使用 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"];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-11
        • 1970-01-01
        • 2021-05-25
        • 1970-01-01
        • 2018-07-12
        • 1970-01-01
        相关资源
        最近更新 更多