更新 1:当 iOS 的数据保护(即密码锁定)关闭时,问题不会发生!
更新 2:禁用 ARC 时不会出现问题。
更新 3:在重新启动 iOS 之前杀死应用程序时不会发生问题。
我的 Settings 类使用 +initialize 实现了单例模式(加上代码以查看发生了什么):
@implementation Settings
static Settings* sharedSettings;
static NSUserDefaults* userDefaults;
+ (void)initialize
{
if ([Settings class] == self)
{
sharedSettings = [self new];
userDefaults = [NSUserDefaults standardUserDefaults];
// Code to see what's going on here ...
if (userDefaults == nil)
{
[[[UIAlertView alloc] initWithTitle:@"userDefaults == nil"
message:nil
delegate:nil
cancelButtonTitle:@"Close"
otherButtonTitles:nil] show];
}
else
{
if ([userDefaults objectForKey:@"Hello"] == nil)
{
[[[UIAlertView alloc] initWithTitle:@"Hello == nil"
message:nil
delegate:nil
cancelButtonTitle:@"Close"
otherButtonTitles:nil] show];
}
else if ([userDefaults boolForKey:@"Hello"] == NO)
{
[[[UIAlertView alloc] initWithTitle:@"Hello == NO"
message:nil
delegate:nil
cancelButtonTitle:@"Close"
otherButtonTitles:nil] show];
}
[userDefaults setBool:YES forKey:@"Hello"];
if ([userDefaults synchronize] == NO)
{
[[[UIAlertView alloc] initWithTitle:@"synchronize == NO"
message:nil
delegate:nil
cancelButtonTitle:@"Close"
otherButtonTitles:nil] show];
}
}
}
}
+ (id)allocWithZone:(NSZone*)zone
{
if (sharedSettings && [Settings class] == self)
{
[NSException raise:NSGenericException format:@"Duplicate Settings singleton creation"];
}
return [super allocWithZone:zone];
}
+ (Settings*)sharedSettings
{
return sharedSettings;
}
@end
我在我的 AppDeletate.m 中触发了这段代码(完全剥离):
#import "AppDelegate.h"
#import "Settings.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
[Settings sharedSettings];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
return YES;
}
@end
现在非常奇怪的是,在重新启动 iOS 后立即运行这个空应用程序时,我会同时得到“同步 == NO”和“Hello == nil”弹出窗口。然后当我杀死该应用程序并再次运行它时,一切都很好。事实证明,当我使用 GCD 的 dispatch_after() 延迟 userDefaults = [NSUserDefaults standardUserDefaults] 和后续语句时(我做了 2 秒,但可能同样没问题),问题就消失了。有人可以告诉我为什么会这样,或者这只是一些极端情况下的 iOS 错误或副作用???
补充:事实证明,当我在重新启动 iOS 之前杀死应用程序时,这个问题就消失了。这对我来说证明了它是 iOS 中的东西。
谢谢收听!
科内利斯
ps:你可以相信我,我完全剥离了我的应用程序,只有三个模块:main.mm(标准XCode生成的单行代码)、AppDelegate.m(完整代码如上所示)和Settings.m(完整代码所示)以上)。所以根本没有其他代码在运行。当我进一步剥离它,只留下 AppDelegate.m 时,问题仍然存在。