使用NSUserDefaults作为全局实例变量的一个坏主意?

时间:2011-08-20 13:30:22

标签: iphone objective-c ipad

我有一个应用程序,当加载主主屏幕时,我在后台检查同步更新。如果连接速度较慢或用户快速浏览应用程序,则会在后台堆叠这些请求。为了防止这种情况,我想实现一个BOOL变量,我切换YES或NO以防止多个请求出去检查同步。

所以我的代码在启动请求时会是这样的:

 NSUserDefaults *d = [NSUserDefaults standardUserDefaults];
 NSString *key = [NSString stringWithFormat:kVarAllowSyncRequest, aManufacturerID];
 [d setBool:NO forKey:key];

我知道这会有效,但在我的应用程序使用过程中会被称为100次 - 这是我甚至需要担心的事情吗?

有没有更好的方法来做到这一点?

3 个答案:

答案 0 :(得分:3)

是的,它会很慢!

放入AppDelegate或为其创建单例 http://blog.mugunthkumar.com/coding/objective-c-singleton-template-for-xcode-4/

答案 1 :(得分:3)

用户默认值是一个放置偏好和信息的好地方,每个会话不会更改或需要访问超过两次或三次的首选项和信息。访问默认值意味着命中磁盘,这很慢;你不想把它用于像每分钟多次检查一个标志那样的东西。

应用程序委托是一个方便的地方,用于存储应用程序中许多对象真正需要访问的信息,因为它始终可以通过[[UIApplication sharedApplication] delegate]访问,但在权衡之前您应该仔细考虑您的应用程序设计用很多伊娃来反对,只是因为看起来很方便。

据推测,只有一个对象,可能是视图控制器,负责发送这些请求。这是举旗的地方。根据您的描述,听起来您根本不需要app-global变量。该标志仅由发起请求的对象使用,因此它是唯一需要了解它的对象。国旗可以是伊瓦尔。

实际上,如果你有一个,它可能有很多实例,每个实例都会发出一个请求,那么正确的解决方案是拥有一个类级别的标志,任何实例有权访问。这很简单。在您的实现文件中,声明一个变量来保存标志:

// RequestMaker.m

#import "RequestMaker.h"

static BOOL allowSyncRequest = YES;

@implementation RequestMaker
// etc.

声明static使其仅在此“编译单元”中可见(松散地,在此文件中)。

然后你创建一个类方法来设置并获得这个标志:

+ (BOOL) allowSyncRequest {
    return allowSyncRequest;
}

+ (void) setAllowSyncRequest: (BOOL)b {
    allowSyncRequest = b;
}

现在,每当您的RequestMaker个实例中的一个想要启动请求时,它应该检查该标志;如果它是YES,那么你可以关闭标志并开始请求。您还需要确保在请求完成时重置标志。

(这都假设您没有明确地为您的请求处理不同的线程。如果您 ,那么您应该查看GCD queues和信号量。这里有一套优秀的信息。 writeups by Mike Ash,即使您不想使用GCD也可以阅读。)

答案 2 :(得分:0)

应该使用

NSUserDefaults来保存通常不会经常更改的值。

最容易实现全局变量的解决方案是将属性添加到您已经可用的单例类 - 您的应用程序委托!这里的代码通常用于需要经常访问应用程序代理的视图控制器中:

// read-only property to return my app delegate
- (MyAppDelegate*)appDelegate {
return (MyAppDelegate*)[[UIApplication sharedApplication] delegate] ;
}

然后,假设您的app delegate上有allowSyncRequest属性,您可以通过以下方式从视图控制器访问它:

self.appDelegate.allowSyncRequest = NO;