2013-12-09 36 views
8

私はアプリのEULAとPPが受け入れられたかどうかを保存するためにNSUserDefaultsを使用しています。私は開始することができます終了し、アプリに戻って、それは値の罰金を読み取ります。私はアプリを終了し、再起動することができます - デフォルトを正常に読み取ります。私は、携帯電話を再起動することができますし、アプリを再起動し、それは正常にデフォルトを読み取ります。フラットバッテリIOS7の後にNSUserDefaultsが読み込まれない理由

しかし、携帯電話がフラットバッテリから再起動すると、アプリを開き、EULAのPPを再度受け入れるよう促されます。これはIOS7の私のiPhone5でのみ発生します。私はIOS6で同じ動作をしない3GSを持っています。

私はそれがhereを解決したのと同じ問題かもしれないと思われますが、これはキーチェーンの権限の問題を指しています。同じアクセス許可の問題がNSUserDefaultsに適用されますか?

NSUserDefaultsを使用してIOS7で同様の問題を経験した人はいますか?

+0

他にも同様の未解決の質問があります。おそらく未解決のバグのように見えます。 NSCoderまたはCore Dataを使用して回避することができます。 –

答えて

21

だから、実験と、私は以下の通りであったために来た結論グーグルで後:ロック画面の背後にあるアプリを起動

重要な更新の変更や、実際に任意のプロセスがここで問題です。ファイル.plist [NSUserDefaults defaultUser]ロードが保護されているので(NSFileProtectionCompleteUntilFirstUserAuthentication)、アプリケーションの起動後に初めてロックが解除されるまでアクセスできなくなります。したがって、プロセスがバックグラウンドでアプリケーションを起動し、アプリケーションがdefaultUserユーザーのデフォルトにアクセスしようとすると、ファイルを読み込むことができないため、新しいデフォルトのユーザー設定が空になります。

ここで私の場合は、受け入れられなかったデフォルト(読み込めなかったもの)から読み込まれるため、EULAとPPが受け入れられるのを待っている状態になりましたまだ。電話のロックを解除してアプリケーションを再起動すると(すでに起動されているので注意してください)、NSUserDefaults、私のアプリケーションのいくつか、私のアプリケーションが使用するライブラリのいくつかのプロセスがあります。ほとんどの場合、デフォルトで同期を呼び出すため、読み込めなかった古いデフォルトを破棄していました。私はこれが多くの人々の場合に当てはまると思います。

いくつかの解決策があります。

まず、NSMutableDictionaryをラップし、ライブラリ/アプリケーションサポートの.plistに辞書を保存するNSUserDefaultsに相当するクラスを作成しました。ファイルの保護をNSFileProtectionNoneに変更しました。機密情報をこのファイルに保存することはお勧めできません。また、ファイルに書き込むたびにそのファイルのアクセス許可を設定する必要があることにも注意してください。何かが好きです:

この方法はうまくいきますが、私はキーチェーンから読み書きしていたデータに別の問題がありました。上記の私の質問のリンク、同じ問題を参照してください。キーチェーンの値は、アプリの起動後最初のロックが解除されるまで同じ保護を持ちます。私はキーチェーンから保護を取り除きたいとは思っていませんでしたが、私は実際にカスタムユーザのデフォルトからプロテクションを削除することはとても快適ではありませんでした。

したがって、次の解決策は問題を実際に解決することです。ロック画面の後ろにアプリが起動されていると保護されたデータにアクセスしようとしないでください!これは、ロック画面の後ろにアプリが起動されたことを検出してから、ユーザーのデフォルトとキーチェーンの値を読み取る前にアプリのロックが解除されるまで待つ必要があることを意味します。

最初の要件は、おそらくapplicationDidLaunchなどの保護されたデータが利用可能な場合に、アプリケーションの起動をチェックすることです。

[[UIApplication sharedApplication]isProtectedDataAvailable] 

アプリが起動したときにこれが当てはまらない場合は、ロック画面の後ろにいることになります。この時点で一時停止し、NSUserDefaultsまたはKeychain(または保護されたファイル)にアクセスする操作は控えてください。保護されたデータが利用可能になったという信号を待つ必要があります。あなたがあなたのアプリケーションの実行に運ぶことができることを受け取ったら

-(void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application 

:ユーザーがロック画面のロックを解除するときappDelegateは、以下を受け取ります。

私の場合は、シングルトンクラスのすべてを制御します。そのクラスが作成されると(唯一のアプリケーションの起動時に起こるもの)私は、保護されたデータが利用可能であるかどうかを確認し、同じ通知のためNSNotificationCenterに加入することを確認します

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(applicationProtectedDataDidBecomeAvailable) name:UIApplicationProtectedDataDidBecomeAvailable object:nil]; 

したがって、この第二の方法で、問題が解決され、データは保護されたままであり、誰もが満足しています。

+0

あなたの答えをありがとう、NSDocumentDirectoryのファイルが画面がロックされているときNSUserDefaultsのように振る舞うのが普通かどうか知っていますか? – franck

+0

@muldercncこれを共有してくれてありがとう。バックグラウンドアプリの更新が開始されてから30分後にユーザーが画面をロック解除した場合でも、バックグラウンドでデータを取得できますか? (OSが切断されるまで1分もかからないので)また、UIBackgroundFetchResultの補完ハンドラをどうすればいいですか? – Serluca

+0

@Serluca私はそう信じています。イベントを生成するので、あなたのアプリはイベントに応答し、30分後でさえもバックグラウンドでそれをうなずけるはずです。確認するためにはもちろんそれを試してみる必要があります。 Xcodeでデバイスコンソールを使用して出力XCODE => Window => Devicesを監視し、テスト中のデバイスのコンソールオプションを使用します(デバッグ中にデバイスを再起動できるため)。 – muldercnc

1

これは、IOS 9.0 GMでの動作です。

関連する問題