11

アプリが最初に開かれたときにユーザーの Documents ディレクトリにコピーされる、事前に入力された .sqlite ファイルを含むアプリがあります。このファイルは 12.9MB です。ターゲットを iOS5 に変更して以来、私のアプリは 2 回拒否されました。次の拒否メモがあります。

Binary Rejected 2012 年 4 月 24 日 10:12 午前

却下の理由:

2.23 アプリは iOS データ ストレージ ガイドラインに従う必要があります。従わない場合は拒否されます

2012 年 4 月 24 日午前 10 時 12 分。アップルから。

2.23

お客様のアプリは、App Store レビュー ガイドラインで義務付けられている iOS データ ストレージ ガイドラインに準拠していないことが判明しました。

特に、コンテンツのダウンロード時にアプリが 12.81 MB を保存することがわかりました。アプリが保存しているデータ量を確認するには:

  • アプリをインストールして起動する
  • [設定] > [iCloud] > [ストレージとバックアップ] > [ストレージの管理] に移動します
  • 必要に応じて「すべてのアプリを表示」をタップ
  • アプリのストレージを確認する

iOS データ ストレージ ガイドラインでは、ユーザーがアプリを使用して作成したコンテンツ (ドキュメント、新しいファイル、編集など) のみを /Documents ディレクトリに保存し、iCloud でバックアップできることを示しています。

アプリで使用される一時ファイルは、/tmp ディレクトリにのみ保存する必要があります。ユーザーがアプリを終了するときに、この場所に保存されているファイルを削除することを忘れないでください。

再作成できるが、アプリが適切に機能するために保持する必要があるデータ、または顧客がオフラインで使用できることを期待しているデータは、「バックアップしない」属性でマークする必要があります。NSURL オブジェクトの場合、NSURLIsExcludedFromBackupKey 属性を追加して、対応するファイルがバックアップされないようにします。CFURLRef オブジェクトの場合、対応する kCFURLIsExcludedFromBackupKey 属性を使用します。

詳細については、テクニカル Q&A 1719: ファイルが iCloud および iTunes にバックアップされないようにするにはどうすればよいですか? を参照してください。

iOS データ ストレージ ガイドラインの要件を満たすようにアプリを修正する必要があります。

データ ストレージ ガイドラインで推奨されているように「バックアップしない」属性を設定しようとしましたが、再び拒否されました。

私は自分のアプリで iCloud を使用しておらず、[設定] > [iCloud] > などで使用状況がまったく表示されません。

データベースは作成後にユーザーによって変更されるため、Cachesまたはディレクトリを使用できません。tmp

Apple がこの種のアプリの機能をまったく許可していないため、私はここで岩と困難な場所の間にいるようです。

誰かがこの問題を抱えていて、それを克服することができましたか?

編集 17-5-12 私はまだこのアプリを承認することができていません。誰かがこれを行うことができましたか?

編集 1-7-12 私のアプリは同じ理由で再び拒否されました。確かに一般的な使用シナリオであるため、ここで何をすべきか途方に暮れています。

EDIT 11-9-12 アプリが承認されました - 以下の私の解決策をご覧ください。それが他の誰かを助けることができることを願っています。

4

4 に答える 4

9

OK、これが私がなんとか承認されたソリューションです(ついに!)

これは、Skip Backup 属性を設定するためのコードです。5.0.1 以前と 5.1 以降では異なることに注意してください。

#include <sys/xattr.h>
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
    if (&NSURLIsExcludedFromBackupKey == nil) { // iOS <= 5.0.1
        const char* filePath = [[URL path] fileSystemRepresentation];

        const char* attrName = "com.apple.MobileBackup";
        u_int8_t attrValue = 1;

        int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
        return result == 0;
    } else { // iOS >= 5.1
        NSError *error = nil;
        [URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
        return error == nil;
    }
}

そして、これが私のものですpersistentStoreCoordinator

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"store.sqlite"];

    NSError *error;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *storePath = [[[self applicationDocumentsDirectory] path] stringByAppendingPathComponent:@"store.sqlite"];

    // For iOS 5.0 - store in Caches and just put up with purging
    // Users should be on at least 5.0.1 anyway
    if ([[[UIDevice currentDevice] systemVersion] isEqualToString:@"5.0"]) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString *cacheDirectory = [paths objectAtIndex:0];
        NSString *oldStorePath = [storePath copy];
        storePath = [cacheDirectory stringByAppendingPathComponent:@"store.sqlite"];
        storeURL = [NSURL URLWithString:storePath];

        // Copy existing file
        if ([fileManager fileExistsAtPath:oldStorePath]) {
            [fileManager copyItemAtPath:oldStorePath toPath:storePath error:NULL];
            [fileManager removeItemAtPath:oldStorePath error:NULL];
        }
    }
    // END iOS 5.0

    if (![fileManager fileExistsAtPath:storePath]) {
        // File doesn't exist - copy it over
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"store" ofType:@"sqlite"];
        if (defaultStorePath) {
            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
        }
    }

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    [self addSkipBackupAttributeToItemAtURL:storeURL];

    return __persistentStoreCoordinator;
}

iOS 5.0 ユーザーの場合は、単に保存しCachesてパージを我慢することにしたことに注意してください。

これは今月Appleによって承認されました。

最初に読んで理解することなく、このコードをコピーして貼り付けないでください。完全に正確ではないか、最適化されていない可能性がありますが、誰かを助ける解決策に導くことができることを願っています.

于 2012-09-11T15:30:53.113 に答える
4
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#include <sys/xattr.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

//Put this in your method

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSURL *pathURL= [NSURL fileURLWithPath:documentsDirectory];

    iOS5 = NO;
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0.1")) {
        iOS5 = YES;
    }

    // Set do not backup attribute to whole folder
    if (iOS5) {
        BOOL success = [self addSkipBackupAttributeToItemAtURL:pathURL];
        if (success) 
            NSLog(@"Marked %@", pathURL);
        else
            NSLog(@"Can't marked %@", pathURL);
    }
}

- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
    const char* filePath = [[URL path] fileSystemRepresentation];
    const char* attrName = "com.apple.MobileBackup";
    u_int8_t attrValue = 1;
    int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
    return result == 0;
}
于 2012-04-25T11:40:19.730 に答える
1

あなたはiCloudを使っていないと言いました。その場合、sqliteファイルを suffix のディレクトリに移動するだけ.nosyncです。それはそれを行う必要があります!

NSString *dataFileName = @"my.sqlite";
NSString *dataFileDirectoryName = @"Data.nosync";
NSString *documentsDirectoryPath = [self applicationDocumentsDirectory];
NSFileManager *fileManager = [NSFileManager defaultManager];

if ([fileManager fileExistsAtPath:[documentsDirectoryPath stringByAppendingPathComponent:dataFileDirectoryName]] == NO) {
    NSError *fileSystemError;
    [fileManager createDirectoryAtPath:[documentsDirectoryPath stringByAppendingPathComponent:dataFileDirectoryName]
           withIntermediateDirectories:YES
    attributes:nil
         error:&fileSystemError];

    if (fileSystemError != nil) {
        NSLog(@"Error creating database directory %@", fileSystemError);
    }
}

NSString *dataFilePath = [[documentsDirectoryPath
                           stringByAppendingPathComponent:dataFileDirectoryName]
                          stringByAppendingPathComponent:dataFileName];

// Move your file at dataFilePath location!

HTH。

于 2012-08-02T07:13:19.053 に答える
0

私はこれを調べていて、このテーマに関する非常に興味深い記事を見つけました: http://iphoneincubator.com/blog/data-management/local-file-storage-in-ios-5

/Documents フォルダーを使用して DB ファイルを保存しようとすると、引き続き拒否されると思います。

弾丸を噛んで /Cache を使用することをお勧めします。最悪のユーザー ケース シナリオは、デバイスのメモリが不足し、アプリがクリーンアップされて DB ファイルが削除されることです。この場合、アプリを再度起動すると、バンドルされた DB ファイルが /Cache にコピーされ、ユーザーは同期してリモート サーバーから余分なデータを取得します。これは、これがアプリの動作方法であると想定しています。

アプリで DB ファイルを /Documents から /Cache に移動するには、NSFileManager にこれを行うように指示するだけです...

#define FILE_MANAGER     [NSFileManager defaultManager]
#define DOCUMENTS_PATH   [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0]
#define CACHES_PATH      [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex: 0]
#define DB_DOCS_PATH     [DOCUMENTS_PATH stringByAppendingPathComponent: @"database.db"]
#define DB_PATH          [CACHES_PATH stringByAppendingPathComponent: @"database.db"]

if([FILE_MANAGER moveItemAtPath: DB_DOCS_PATH toPath:DB_PATH error:&error])
    {
        NSLog(@"SUCCESSFULLY MOVED %@ to %@",DB_DOCS_PATH,DB_PATH);
    }

これにより、既存のユーザーが iCloud ストレージを不必要に使用するのを防ぐことができます。

于 2012-07-02T14:06:15.747 に答える