18

私のアプリの 1 つに対する重要なバグ修正アップデートが、iCloud データ ストレージ ガイドラインに違反している疑いがあるため、最近拒否されました。

私のアプリがデータを保存する方法は次のとおりです (私のアプリの最初のバージョンが 2009 年に承認されて以来、問題はありませんでした)。

  1. 起動時に、「スターター」SQLite3 データベースをアプリ バンドルからドキュメント フォルダーにコピーします。
  2. データベースには、基本的なスキーマといくつかのサンプル データが含まれているため、ユーザーはアプリの使用方法を確認できます。それは小さく、わずか 3MB 未満です。
  3. ユーザーの今後の作業は、このデータベース ファイルにのみ保存されます。彼らはサンプルを削除したり保持したり、独自のデータを大量に追加したりするかもしれませんが、そのデータベース ファイルは常にそこにあります。

今年初めのアップデートも同様の理由で却下されましたが、上記の説明をしたところ、アプリのステータスが「却下」→「審査中」→「App Storeで処理中」に変わっていました。彼らは私に何の説明も送ってくれなかったので、レビュアー側の単なる誤解だと思いました.

今回、レビュアーは私の説明に対して、ユーザーが生成したもの以外のデータは iCloud に保存すべきではなく、アップデートは「拒否」状態のままであると単純に答えました。

しかし、私はここで何をすべきか理解していません。ユーザーの作業はすべてデータベースに保存されるため、これを iCloud バックアップから除外したり、キャッシュ フォルダーに保存したりすることはできません。また、アプリは同じデータベース ファイルから動作するため、「ユーザーが生成した」データと「ユーザーが生成していない」データをきれいに分離することはできません。データベースのファイル名とディレクトリの場所は同じままですが、初期の非ユーザー生成データはユーザー自身のデータにすぐに置き換えられます。

また、データベースにサンプル データがなくても、データベースを利用するアプリは起動時に空のデータベースを生成する必要があります。アプリのデータベース スキーマだけが保持されている場合でも同様です。

これは非常に一般的な問題に違いありませんが、残念ながら、バックアップをオフにするだけでは問題ありません。ユーザーは、私のアプリに保存するデータに多くの労力を費やしており、iCloud バックアップは彼らにとって非常に重要です。

この時点でどのようなオプションがありますか? ここに私が見ることができるものがあります:

  1. もう一度 Apple に連絡して、何が起こっているのか説明してみてください。

  2. ファイルのバックアップ属性を NO に設定し、ユーザーが最初の変更を行ったときにのみ YES に切り替えることはできますか? それは技術的に大丈夫ですか、そしてAppleと大丈夫ですか?

  3. サンプル データをデータベースから削除します。これはユーザビリティに非常に悪いものであり、サポートの負荷が増大しますが、更新が承認されるのであれば喜んで実行します。ただし、空のデータベース スキーマを保持するために起動時にスタブ データベースを作成する必要があるため、承認プロセスに違いが生じるかどうかはわかりません。

  4. 泣く。

誰にもアドバイスはありますか?私と同じようにデータベースを使用するアプリが他にもたくさんあると想像する必要がありますが、バックアップを無効にするオプションはありません。

また、私が行った変更には別のテストとアプリのレビューが必要になることも非常に憂鬱です。これにより、重要な更新がさらに2〜3週間遅れます. :/

更新:別のオプションがあるかもしれません:ドキュメントフォルダーの使用に特に問題があるように思われるため、単にファイルを のLibrary/代わりに保存できますか? Documents/ファイルが に保存されている場合、ファイルはバックアップされLibrary/ますか?

更新 2 : 私が最も混乱しているのは、データベースに支えられたアプリ (コア データを使用している場合でも) は、少なくともアプリのスキーマを含むデータベース ファイルを作成する必要があることです。問題は、データベースのサイズが大きすぎることだけですか? データベースに支えられたアプリケーションが、起動時にデータベースを作成する必要を回避する方法がわからないためです。

更新 3 : Core Data ではなく、カスタム SQLite インタラクション レイヤーを使用しています。また、サンプル データはスターター イメージで構成されており、ユーザーがアプリの使用を開始すると、おそらくそれらを削除することになります。

4

8 に答える 8

5

3MB というのは、データベースに格納されているサンプル データの量がかなり多いように思えます。代わりに、画像を取り出して画像への参照をデータベースに保存すると、この使用量を大幅に削減できるはずです。その後、データベースのイメージ ゲッター コードを次のように変更できます。

- (UIImage *)image
{
    NSString *imageName = self.imageName;
    UIImage *image = [UIImage imageNamed:imageName];
    if (!image)
    {
        NSString *imageLibraryPath = ...;
        image = [UIImage imageWithPath:[imageLibraryPath stringByAddingPathComponent:imageName]];
    }
    return image;
}

- (void)setImage:(UIImage *)image
{
    [self setImageData:UIImagePNGRepresentation(image)];
}

- (void)setImageData:(NSData *)imageData
{
    NSString *imageLibraryPath = ...;
    NSString *fileName = self.uniqueId; //or something else, UUID maybe?
    NSString *filePath = [imageLibraryPath stringByAddingPathComponent:imageName];
    [imageData writeToFile:filePath atomically:YES]; // maybe dispatch_async this into the background?
    self.fileName = fileName;
}

self.fileName、データベースによってサポートされます。

この方法でデータ ストレージを削減することで、電話に比較的大量のデータを保存していないため、承認を受けることができます。画像もこの方法でアプリ バンドルに含めることができ、複製する必要はまったくありません。

于 2012-07-09T15:11:07.710 に答える
4

私は本当にばかげた考えを持っています。しかし、おそらくそれは有効です。

起動時に「デモ データを作成しますか」というポップアップを表示できます。ユーザーが「はい」をクリックすると、そのユーザー生成データ。

于 2012-07-11T11:11:59.073 に答える
3

回避策の 1 つは、ユーザーが何かを編集しようとするまで、バンドルから SQL ファイルを読み取ることです。次に、それをコピーします。ファイルは小さいので、スピナーも必要ありません。

最近、アプリでこの正確な問題が発生しました。私たちの場合、コア データを使用し、起動時に SQL ファイルもコピーしました。

残念ながら、iOS 5 をターゲットにする必要があります。

https://developer.apple.com/library/ios/qa/qa1719/_index.html

于 2012-07-07T12:32:14.187 に答える
0

究極の解決策として、既定のデータを追加の読み取り専用永続ストアとして使用する CoreData を使用することをお勧めします。

ただし、当面は、簡単で迅速な解決策が必要です。サンプル データをユーザーのデータベースにロードする簡単な画面を作成します。「システム」または「ツール」画面にリンクを配置して、いつでも実行できるようにします。

ただし、具体的には、アプリを最初に実行したときに表示します。ドキュメントにサンプルデータが必要かどうか、データのサイズをユーザーに尋ねているので、ドキュメントを作成するのはユーザーです。また、サンプル データはいつでも削除または置換できることにも注意してください。

これでレビューを通過できるはずです。

于 2012-07-10T15:46:27.033 に答える
0

「プライベート」SQL データ アクセス レイヤーの使用

Core Data ではなくカスタム アクセス レイヤーを使用しているため、「初期シード」データベースを iCloud フォルダーに配置するのではなく、実行時にそれを生成するカスタム プロシージャを作成することをお勧めします (たとえば、最初にアプリ)。

最善の方法は、実際の SQL ファイルを iCloud 共有フォルダーの外にある共通のアプリケーション バンドルに配置することです。手順に従って、このファイルのすべてのコンテンツを読み取り、共有フォルダーにクローンを再作成して、この新しいファイルがバンドルされたコンテンツではなくユーザー生成コンテンツとして表示されるようにする必要があります。これには無駄なオーバーヘッドが少し必要になりますが、Apple がアプリを拒否しないようにするために必要だと思います。

ダウンロードしたすべてのアプリに既に存在し、iCloud の貴重なスペースを無駄に占有するため、可能であれば、すべての画像をバックアップせずにメインバンドルに残しておくことをお勧めします。絶対に必要なものだけをiCloudに置くようにしてください。

Core Data と iCloud を併用する予定の場合。

まず第一に、iCloud にカスタム SQLite3 データベース ファイルを配置することは、いくつかの理由で危険です。最初の理由は、アプリが異なるデバイスで同時に使用されている場合、異なるデータ間のマージの問題を適切に処理できないという事実です。

時間とスペースが必要になるため、ここで完全な解決策を提供することはできません。しかし、今年の Apple WWDC のセッション 227 の講演を見ることをお勧めします。彼らは Core Data と iCloud を一緒に使うことについて話し、あなたが現在直面している同じ問題 (つまり、iCloud を介した最初のデータベースのシードと同期) にも対処しています。Apple Developer ポータルから WWDC ページにアクセスすると、サンプル プロジェクトの完全なコピーを入手できます。

于 2012-07-09T14:30:45.187 に答える
0

次の属性を追加するだけで、Apple はパスを許可します (使用していない場合)

    #include <sys/xattr.h>
    ...
    - (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
    {
    int result = -1;
    @try {
            const char* filePath = [[URL path] fileSystemRepresentation];
            const char* attrName = "com.apple.MobileBackup";
            u_int8_t attrValue = 1;
            result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
    } @catch (NSException * e) {
            DebugLog(@"Exception: %@", e);
    }
    return result == 0;
    }

    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    ... 
    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
    [self addSkipBackupAttributeToItemAtURL:storeUrl];
    ...
于 2012-07-09T20:41:04.107 に答える
0

CoreData と 2 つの永続ストアが最適です。ただし、最初にファイルをコピーするときに、com.apple.MobileBackup ファイル属性を設定します。ユーザーが最初の変更を行った後、設定を解除します

于 2012-07-10T13:37:20.310 に答える
-1

Core Dataを使用している場合は、サンプルデータをアプリバンドルに保持できます。docsディレクトリの読み取り/書き込みストアと同じコーディネーターで読み取り専用の永続ストアとして開きます。CoreDataを使用すると、保存時に適切な場所に保存されます。これは、WWDC2012の「コアデータを使用するためのベストプラクティス」ビデオで説明されています。

SQLiteを直接使用している場合、それはそれほど簡単ではありませんが、同じことを行うための独自のロジックを実装できます。

于 2012-07-09T14:40:37.347 に答える