22

TinyWingsのバグ修正に奇妙な問題があります。私のゲームでは、次のようなものを使用します。

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];      
[userDefaults setFloat:musicVolume forKey:@"musicVolume"];

いくつかの設定とハイスコアテーブルを保存するため。ゲームの終了時にゲームオーバー画面が表示されると、ゲームはハイスコアをstandardUserDefaultsに保存します。ゲームが次のようなUIAlertViewを表示するまで、これは非常にうまく機能します。

UIAlertView *alert = [[UIAlertView alloc] init];
[alert setTitle:@"Get ready!"];
[alert setDelegate:self];
[alert addButtonWithTitle:@"Ok"];
[alert show];
[alert release];

ゲームがstandardUserDefaultsに何かを保存するたびにAlertViewが消えた後、ゲームはしばらく遅れます(一部のデバイスでは数秒間)。これは、ゲームがプレーヤー名を入力するためにUITextFieldを使用した後にも発生します。2つのUIKit要素のいずれかが使用される前はゲームに遅れはありませんが、それらを使用した後は、アプリを再起動するまでゲームが遅れます。パフォーマンスツールの問題を分析しましたが、「I / Oアクティビティ」インスツルメントは、

/System/Library/Frameworks/UIKit.framework/InputModeProperties.plist

これが遅れの原因になります。

私は全く何をすべきか見当がつかない。何か案は?

編集:
アップルデベロッパフォーラムhttp://devforums.apple.com/message/424374#424374にスレッドがあり、誰かが同じ問題を抱えており、iOS4.3でのみ表示されるようです。私はそれをテストしましたが、ラグは私の4.3デバイスでのみ発生します(3.1 iPodTouchおよび4.2iPadでは発生しません)。

4

6 に答える 6

3

わかりました。周りを見回すと、InputModeProperties.plistはハードウェアとソフトウェアのキーボードの単なるリストのようです。

この問題を投稿したフォーラムスレッドを見ると、基本的に、UITextFieldオブジェクトまたはUIAlertView(特にUITextInputTraits.hを含む)をロードした後、ユーザーのデフォルトを保存しようとすると、キーボード定義ファイルの不可解なループが発生するようです。これはiOS4.3でのみ発生します。

私にはUIKitのバグのように思えますが、突然UIKitが実際の目的のためにたくさんのものを節約していると思います。この場合、これらの要素を回避することはできますが(アラートにはそれほど悪くはありませんが、テキストフィールドはトリッキーになります)、コアデータに切り替えることはできますが、それについて何もするのは難しいかもしれません。または、すべてのオプションに対して変更可能な辞書を作成し、アプリが閉じて一時停止を気にしないときに、それをユーザーのデフォルトに保存することもできます。または、アップデートを実行するだけです。

頑張ってください(ゲームが大好きです)

于 2011-05-26T14:12:11.633 に答える
3

編集

まともなバグの回避策:

短いバージョン:ユーザーが煩わしくなるまで、バグをトリガーする呼び出しを遅らせるだけです。

ロングバージョン:

問題は呼び出しから来ていると思うので、キーボードレイアウトを要求するアクション[NSUserDefaults standardUserDefaults]の後にそのダーティなplist-loadingループをトリガーしますUIAlert(のような)...

[NSUserDefaults standardUserDefaults]アプリの読み込み時にバグの原因となる呼び出しの前に)一度だけ呼び出し、返された参照をすべてのアプリのライフサイクルの間シングルトンクラスに保持することをお勧めします。私はメモリフットプリントが巨大になるとは思わない...(私は問題なくいくつかのアプリでこれを行っています)。さらに悪いことに、plistの読み込み* 100はアプリの読み込み時に1回だけ実行され、ゲーム中には実行されません。

問題が[userDefaults setXxxx:...]呼び出しに起因する場合、同じ回避策として、値をメモリに保存し、同期する直前userDefaultsのように後で設定することができます...ただし、クラッシュなどの問題が発生した場合に情報が失われるリスクがあります。私は個人的に、データの整合性を確保するために、それぞれの後に行うことを好みます...syncset

ENDOFEDIT


簡単な答え:iOS4.3のバグ、回避策を見つける機会はほとんどありません...バグレポートと次のiOSアップデートを待ちます...2週間でWWDC... 1〜2か月。

長いもの:

UIKitアセンブリを見た後、ここに私の推測があります:

  • InputModeProperties.plistロケールごとのすべてのキーボードレイアウトのリストが含まれています。
  • UIKitキーボードを表示するときなど、いくつかの目的でこれを使用して、使用可能なキーボードレイアウトを決定します。(ロケール...)
  • 興味深いのは、その情報のいくつかを次の場所に見つけることができるということですNSUserDefaults

    NSLog(@"%@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
    ==> {
    AppleKeyboards =     (          // I have two keyboard in preferences
       "fr_FR@hw=French;sw=AZERTY", // french  first
       "en_US@hw=US;sw=QWERTY"      // english second
    );
    ...
    
  • ただし、これらの情報は、スコアとは異なり、アプリの設定には保存されません。(NSGlobalDomain、またはより可能性が高いのは、ユーザーの優先言語ごとに別々のドメイン
  • したがって、UIKit + NSUserDefaultsに競合(バグ)が存在し、そのダーティなplistロードループが発生することは驚くことではありません。
  • あなたが言う約100の電話?これは、plist内のロケール/レイアウトの数のようなものです!

で使用できるキーボードがない場合NSUserDefaults...(同期後のように、これを行うバグを想像してみましょう)...UIKit使用可能なすべてのキーボードを試してユーザー1を判別し、この4.4Kplistを100回汚く解析します...を表示するときのようにUIAlertView。 ..NSUSerDefault同期/変更後。

知るか?ソースコードを持っているアップルの人々:)

デフォルトのUS以外のキーボードを設定する設定に移動してから、USに戻すと問題が解決するので、驚くことではありません。あなたの場合は役に立たないが、問題を確認するだろう。別の4.3のバグのためにそれを見ました...

他の人が言ったように、NSUserDefaultsを使用せずに、/ Documentsの単純なカスタムplistを使用することは、(不適切な)適切な回避策になる可能性があります。

Tiny Wingsの素晴らしい仕事です!:)

于 2011-05-27T23:47:23.380 に答える
2

UIKitとOpenGLを一緒に使用することはお勧めしません。この見方は、両者を混ぜ合わせるという考え方ほど問題ではないと思います。そのアラートを修正し、代わりにカスタムオーバーレイを表示して、次の2つのことを実行できるようにすることを強くお勧めします。

  1. 「GetReady」アラートをゲームのグラフィックと一致させます。
  2. この問題は完全に避けてください。

第2世代のiPodtouchでゲームを再開すると、AppStoreで現在リリースされているバージョンのパフォーマンスが低下します。

これらの要素をそのままにしておきたい場合は、このApple Developer Forumの投稿で、同期を別のスレッドで実行することをお勧めします。それで、私はこれらのステップを提案します:

  1. 他の提案として、NSUserDefaultsへの参照をどこかに保持します。(私は通常、次のようなことをし#define kSettings [NSUserDefaults standardUserDefaults]ます。もちろん、シングルトンをインスタンス化するには、一度呼び出す必要があります。)

  2. 2番目のスレッドで呼び出しを実行しsynchronizeます(Apple Developer Forumの投稿による)。

  3. synchronize以外の時間に電話をかけることができるかどうかを確認してくださいwillResignActive。そのメソッドからsynchronizeを呼び出すと、問題は少し悪化するようです。

ゲームおめでとうございます。

于 2011-05-29T12:52:24.513 に答える
1

4.3diffを見て暗闇の中でのショット-

おそらく新しいものの組み合わせ

- (BOOL)disablesAutomaticKeyboardDismissal

UIViewControllerとUIModalPresentationFormSheet(これはデフォルトでYESになっています)で、コードにある種のループが発生しています。

于 2011-05-23T10:11:24.283 に答える
1

アラートビューを表示するメソッドを実行すると仮定して、次のことを試しましたか?

[self performSelector:@selector(displayAlert) withObject:nil afterDelay:0.5];

- (void)displayAlert {
  UIAlertView *alert = [[UIAlertView alloc] init];
  [alert setTitle:@"Get ready!"];
  [alert setDelegate:self];
  [alert addButtonWithTitle:@"Ok"];
  [alert show];
  [alert release];
}

私が尋ねる理由は、同期の直後にメソッドを実行しようとすると、奇妙な動作を頻繁に経験するためNSUserDefaultsです。そうでなければ、何が起こっているのかを判断するために、もう少しコードを見る必要があります。

于 2011-05-24T06:13:56.487 に答える
1

おそらく、各オプションを個別のトランザクションとして保存します。わからない。NSMutableDictonairyをデータストレージとして使用して、独自のシングルトンDataStorageクラスを使用してみることができます。applicationDidEnterBackground:そして、それをとのNSUserDefaultsに同期しapplicationWillTerminate:ます。または、NSUserDefaultsでシステム設定を使用していなくても、このNSMutableDictonairyを次のように保存できます。

tempData = [NSMutableData data];
archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:tempData];
[archiver encodeObject:mutableDict forKey:@"data"];
[archiver finishEncoding];
result = [tempData writeToFile:archivePath atomically:YES];
[archiver release];

psは小さな翼に親指を立てます。;)

于 2011-05-26T09:03:23.963 に答える