更新 1: iOS のデータ保護 (つまり、パスコード ロック) がオフの場合、問題は発生しません!
更新 2: ARC が無効になっている場合、問題は発生しません。
更新 3: iOS を再起動する前にアプリを強制終了しても、問題は発生しません。
私の設定クラスは、 +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 を再起動した直後にこの空のアプリを実行すると、「同期 == NO」と「Hello == nil」の両方のポップアップが表示されることです。その後、アプリを強制終了して再度実行すると、すべて問題ありません。userDefaults = [NSUserDefaults standardUserDefaults] と、GCD の dispatch_after() を使用した後続のステートメントを少し遅らせると (2 秒間実行しましたが、おそらくそれよりも短い時間で十分です)、問題が解決することがわかりました。誰かがこれがなぜなのか、またはこれは単純なコーナーケースの iOS バグまたは副作用なのか教えてもらえますか?
追加: iOS を再起動する前にアプリを強制終了すると、この問題は解決することがわかりました。これは私にとって、それがiOSの何かであることを証明しています。
聞いてくれてありがとう!
コーネリス
ps: 信じてください。アプリを完全に削除しました。モジュールは 3 つだけです: main.mm (標準の XCode によって生成されたワンライナー)、AppDelegate.m (上記の完全なコード)、および Settings.m (完全なコードが表示されています)その上)。したがって、他のコードはまったく実行されていません。AppDelegate.m だけを残してさらに削除すると、問題は残りました。