在今日小组件上保存和加载数据(iOS 8)

8

在Today Extension中使用NSUserDefaults保存和加载数据是否可行?关闭通知中心后,小部件的行为类似于被终止的应用程序,因此任何数据结果都会丢失。我该如何解决这个问题?

以下是我的代码:

NSUserDefaults *defaults;

- (void)viewDidLoad {

[super viewDidLoad];

defaults = [NSUserDefaults standardUserDefaults];
NSArray *loadStrings = [defaults stringArrayForKey:@"savedStrings"];

if ([loadStrings objectAtIndex:0] != nil) {
    [display setText:[NSString stringWithFormat:@"%@", [loadStrings objectAtIndex:0]]];
}
if ([loadStrings objectAtIndex:1] != nil) {
    calculatorMemory = [NSString stringWithFormat:@"%@", [loadStrings objectAtIndex:1]].doubleValue;
}

}


- (IBAction)saveData:(id)sender {

NSString *displayString;
NSString *memoryString;

NSArray *saveStrings = [[NSArray alloc] initWithObjects: displayString, memoryString, nil];


defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveStrings forKey:@"savedStrings"];
[defaults synchronize];


}

5个回答

19

您需要使用应用程序组标识符而不是com.*,例如:

NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:@"group.company.appgroup"];

存储数据时,不要忘记同步

[shared synchronize];

谢谢,不过在深入阅读文档后,两天前我已经按照你所说的解决了问题! - Massimo Piazza
@MassimoPiazza 我已经按照步骤进行操作,但它并没有起作用。我在处理键盘应用程序扩展。你有什么想法吗? - Spentak
4
这个主题的教程很棒,链接为http://www.glimsoft.com/06/28/ios-8-today-extension-tutorial/。 - CVertex
@Spentak:你在键盘扩展上实现了吗?我按照同样的步骤进行,但对我也不起作用。 - Muzammil
该死...在iOS 9.1上我已经尝试了两天,但它还是无法工作。 - Patel Jigar
显示剩余2条评论

2

如果您想知道如何保存和获取值,请看以下代码。

在您的常规应用程序中,将以下内容添加到您的 *.m 文件中即可保存任何您喜欢的内容。

NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:@"group.yourcompanyname.TodayExtensionSharingDefaults"];

    //save dic
    [shared setObject:dictionary2 forKey:@"dicForTodayWidget"];

    //save array
    [shared setObject:tempArray2 forKey:@"arrayForTodayWidget"];

    //save some value
    [shared setObject:@"1234" forKey:@"myValForTodayWidget"];

    [shared synchronize];

在TodayViewController.m文件的viewDidLoad方法中添加以下内容,以在您的今日小部件中显示:
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:@"group.yourcompanyname.TodayExtensionSharingDefaults"];

    //get dic
    NSMutableDictionary *dictionary = [shared objectForKey:@"dicForTodayWidget"];

2
您需要添加此处详细说明的应用组内容,然后如果它实际起作用(在测试版下可能不确定),它应该允许您像正常情况下一样在主机和小部件之间共享NSUserDefaults数据。
编辑:普通的NSUserDefaults 无法使用。苹果已经实现了一种新的方法。使用时,只需像这样重新定义您的NSUserDefaults实例:
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:@"com.you.app.container"];

@BalestraPatrick 确保应用程序组已正确配置,并为您的应用程序目标和扩展目标以及您的应用程序 ID 和预配配置文件配置了正确的权限。 - Andrew
1
似乎这在iOS键盘扩展上无法工作。 - Spentak

1

你需要先为应用程序和扩展设置App Groups。

然后,使用

NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:@"group.company.myapp"];

要获取默认对象,您可以像往常一样读取/写入。

如果您想被通知有关默认值的更改,请在您的小部件(或应用程序)中使用NSUserDefaultsDidChangeNotification

有关详细信息和逐步教程,请查看博客文章


跟随教程尝试使用键盘应用扩展,但未能正常运作。 - Spentak
@Spentak 嗯,那很奇怪。具体是什么出了问题?此外,教程(以及这个SO问题)是关于今天的扩展,键盘扩展的限制要小得多 - 也许它们在NSUserDefaults或其他方面有一些限制。 - Lukas Petr
Lukas - 你能让用户默认设置在键盘扩展中工作吗? 我已经测试过了,但无法成功通过测试用例。 - Spentak
2
你尝试过使用NSUserDefaultsDidChangeNotification吗?我无法收到通知,似乎其他人也是如此,但我找不到任何官方文档,所以我仍然想知道是否有可能。 - hagi
Hagi - 你找到如何使NSUserDefaultsDidChangeNotification工作的解决方案了吗?对我来说也不起作用。我可以检查值从主应用程序更改为扩展,并使用每秒触发的计时器进行检查。但是,即使值已更改,通知也不会出现。我使用组,我使用initWithSuiteName进行用户默认值初始化。我可以访问值。因此,除了通知之外,一切都正常。我通过addObserver:selector:name:object:将通知中心观察者添加到我的扩展中,并使用对象值nil。但它不起作用。 - edukulele

-2

今天扩展和主应用程序在两个进程上运行。今天扩展无法接收NSUserDefaultsDidChangeNotifications。我尝试使用MMWormhole。它非常好。


虽然此链接可能回答了问题,但最好在此处包含答案的必要部分并提供该链接以供参考。仅有链接的答案如果链接页面发生更改可能会变得无效。 - 【来自审核】 - Kara
我的答案包括这个库。如何使用该库,请访问此链接。我认为非常容易。现在我已经删除了那个链接。 - minus_one

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接