更新1:当iOS的数据保护(即密码锁定)关闭时,不会发生问题!
更新2:禁用ARC时不会发生问题。
更新3:在重启iOS之前杀死应用程序时不会发生问题。
My Settings类使用+ initialize实现Singleton模式(加上代码以查看发生了什么):
@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后立即运行这个空应用程序时,我得到“synchronize == NO”和“Hello == nil”弹出窗口。当我杀死应用程序然后再次运行时,一切都很好。 事实证明,当我使用GCD的dispatch_after()延迟userDefaults = [NSUserDefaults standardUserDefaults]和后续语句时,一点点(我做了2秒,但可能会少得多)可能会消失。 有人可以告诉我为什么会这样,或者这是一个简单的角色案例iOS bug还是副作用???
附加:事实证明,当我在重启iOS之前杀死应用程序时,这个问题就消失了。这对我来说证明它是iOS中的东西。
感谢收听!
科内利斯
ps:你可以相信我,我完全剥离了我的应用程序,只有三个模块:main.mm(标准XCode生成单行),AppDelegate.m(上面显示的完整代码)和Settings.m(上面显示的完整代码)。所以根本没有其他代码运行。 当我进一步剥离它,只留下AppDelegate.m时,问题仍然存在。答案 0 :(得分:2)
在+initialize
期间,您不应该引用其他类。关于它何时运行以及此时存在的其他类没有任何承诺。 +initialize
应该只做内部到课堂的工作。
自添加GCD以来,该单例模式已被取代。您应该出于各种原因使用GCD模式,其中一个原因是当您认为它运行时它会运行。
How do I implement an Objective-C singleton that is compatible with ARC?
作为一个说明,我对你的main.mm
感到好奇。制作顶级ObjC ++几乎总是一个坏主意,并可能导致一些令人惊讶的副作用。 (ObjC ++是一种古怪的粘合语言,有很多奇怪的行为。你应该在尽可能少的类中使用它。)我个人会看到将这个更改回.m
是否解决了问题,尽管我仍然建议使用GCD -Singleton而不是+initialize
。