如何在AppDelegate中使用NSUserDefaults

6
我试图使用NSUserdefaults从文本字段中保存一些数据,我希望在应用程序退出时保存它,并在应用程序启动时加载它,但是我遇到了一些问题。
我想要使用的方法都在AppDelegate中,但是我不太了解如何使用AppDelegate,我想到了两种可能的方法来实现这个目标,但我不知道它是否可行。
1.导入AppDelegate并覆盖我的VC中的方法 或者 2.在AppDelegate中创建我的VC的实例,并允许AppDelegate设置和检索我的UITextField的文本-(这是否违背MVC范式?)
感谢您的建议。
非常感谢您的时间。
4个回答

4
与其在AppDelegate中保留文本字段,不如保留文本。我会按照以下方式进行操作:
1)在AppDelegate.h文件中:
@property (strong, nonatomic) NSString *textToBeSaved;

2) 在AppDelegate.m中,当您的应用程序启动和终止时,请读取并将textToBeSaved写入NSUserDefaults。在启动时:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.textToBeSaved = [defaults objectForKey:@"save_me"];

并且,在终止之前:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:self.textToBeSaved forKey:@"save_me"];
BOOL success = [defaults synchronize];

3) 在自然拥有UITextField的SomeViewController.m中,在viewWillAppear中:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
myTextField.text = appDelegate.textToBeSaved;

4) 当你设置textToBeSaved取决于你的用户界面时,但每当你知道文本已准备好(例如,在textFieldShouldReturn或shouldEndEditing中),你可以将字符串交给AppDelegate:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.textToBeSaved = myTextField.text;

如果没有UI让用户接受文本,你可以将字符串保存在(textField:shouldChangeCharactersInRange:replacementString)中。

2
如您所述,您有两个选择:
1)从AppDelegate的applicationDidFinishLaunching和applicationWillTerminate方法直接访问VC的UITextField。
在applicationDidFinishLaunching中:
从NSUserDefaults读取,设置VC中的UITextField。
在applicationWillTerminate中:
从VC中读取UITextField,设置NSUserDefaults并同步。
2)在VC中创建适当的方法来完成相同的工作,并从AppDelegate中调用它们。
-(void)record
{
// Read from UITextField, set UserDefaults and synchonize.
}

-(void)restore
{
// Read from UserDefaults, set UITextField.
}

感谢您的输入,第二种方法听起来对我来说更容易哈哈。但是将我的VC导入到AppDelegate中不被认为是不好的吗?还是允许的?由于我没有将我的VC连接到AppDelegate,似乎找不到如何连接或者我只需要创建一个实例即可。 - user1214037
如果它是您唯一的VC,则默认情况下已由rootViewController访问。您可以在AppDelegate中像这样调用它们:[self.rootViewController record]; - erkanyildiz
这只是其中之一 :). 我正在使用一个故事板,同时我删除了原始的故事板以使用导航控制器。 - user1214037
其实我从来没有用过Storyboard,但你所要做的就是跟踪你的VC。我的意思是,保持对你的VC实例的引用,就像rootViewController一样。 - erkanyildiz
好的,非常感谢你的帮助。我会在尝试后标记为已解决。 - user1214037

1
我建议您在子类中注册一些UIApplication通知,并适当地响应它们。这里是UIApplication文档的链接。您可以订阅的通知在页面底部列出。

http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplication_Class/Reference/Reference.html

以下是您在子类中可能执行的示例:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         Selector:@selector(restore)
                                             name:UIApplicationDidFinishLaunchingNotification
                                          object :nil];

别忘了将自己也从观察者中移除。如果你对 NSNotifications 不太熟悉,网上有很多教程可以参考。


0

在 App Delegate 中持有视图控制器链的引用是被允许的。苹果自己的示例和 iOS 应用程序模板经常将指向根视图控制器的指针放在 App Delegate 实例变量中。

如果视图控制器链没有被打破,一种可能的方法是让 App Delegate 向顶部或根视图控制器发送一个 "cleanUpNow" 消息,并让视图控制器将其传递下去,每个视图控制器根据需要进行清理,然后将该消息重新发送到链中更远的所有其他控制器以进行清理。

直接进入另一个视图控制器可能不如发送它一个清理自身的消息(写入 NSDefaults 等)。或者让它们所有人都向一个中央的 "清理" 控制器对象发送消息,该对象的目的是收集所有必要的状态并将其以一个连贯的块写出。

如果链断开了,另一个选项是让 App Delegate 发送一个通知,需要清理的任何控制器都可以注册处理程序来处理该 "清理" 通知。


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