web-dev-qa-db-ja.com

NSFileManager作成フォルダー(Cocoaエラー513)

アプリの/ soundsフォルダー内にフォルダーを作成しようとしています。

-(void)productPurchased:(UAProduct*) product {
    NSLog(@"[StoreFrontDelegate] Purchased: %@ -- %@", product.productIdentifier, product.title);

    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];

    NSError *error;

    NSString *dataPath = [NSString stringWithFormat:@"%@/sounds/%@", bundleRoot, product.title];

    if (![manager fileExistsAtPath:dataPath isDirectory:YES]) {
        [manager createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&error];
        NSLog(@"Creating folder");
    }

    NSLog(@"%@", error);
}

しかし、私はこのエラーを受け取ります:

Error Domain=NSCocoaErrorDomain Code=513 "The operation couldn’t be completed. (Cocoa error 513.)" UserInfo=0x175120 {NSFilePath=/var/mobile/Applications/D83FDFF9-2600-4056-9047-05F82633A2E4/App.app/sounds/Test Tones, NSUnderlyingError=0x117520 "The operation couldn’t be completed. Operation not permitted"}

私は何が間違っているのですか?ありがとう。

24
Iñigo Beitia

エラードメインでGoogleを検索すると、 NSCocoaErrorDomain コード513はエラーに変換されます NSFileWriteNoPermissionError

これにより、この問題を解決するための重要な手がかりが得られます。

これは、アプリケーション自体を含むバンドルディレクトリです。アプリケーションは署名する必要があるため、実行時にこのディレクトリの内容を変更しないでください。変更すると、アプリケーションが後で起動できなくなる可能性があります。

具体的には、コンパイルされたアプリのバンドルフォルダーの内容を変更することはできません。これは、バンドルがコンパイル済みアプリケーションであるためです。

最終的にiTunesApp Storeを通じてアプリを配布すると、アプリケーションには、アプリのコンテンツを検証するデジタル署名が付けられます。この署名はコンパイル時に生成されます。

コンパイル後にバンドルを変更しようとすると、アプリが変更され、デジタル署名が無効になります。これはアプリケーションを無効にします—そこにどんなコードがあるか誰が知っていますか? —そしてエンドユーザーはそれを実行することができなくなります。したがって、Appleは、バンドルを変更しようとするとエラーをスローするようにiOSを設定しました。

バンドルに書き込む代わりに、アプリは 受け入れられている3つのアプリ固有のフォルダーの1つDocumentsTemp、およびCacheに書き込むことができます。ほとんどの場合、Documentsフォルダーに書き込みます。

これらのフォルダーには、アプリからのみアクセスできます。他のアプリはこれらのフォルダーの内容にアクセスできません。 (同様に、アプリは別のアプリのフォルダーにアクセスできません。)

デスクトップファイル共有サポート を介して、エンドユーザーがiTunesを介してファイルデータへのアクセスを管理できるようにアプリを設定できます。

51
Alex Reynolds

これは、実行時にアプリケーションのバンドルを変更してはならないためです。代わりに、リソースを追加できるフォルダーを別の場所に配置する必要があります。

編集:
表示されているエラーは、バンドルに書き込めないことが原因である可能性があります。

7
jrtc27

Logライブラリを使用すると、同じ問題が発生します。最後に、それはパスフォーマットの問題です。 dataPath形式を確認してください。 Case 1の場合、有効です。私の場合はCase 2なので、ディレクトリの作成に失敗しました。

// Case 1
/var/mobile/Containers/Data/Application/5FB2CD2D-91DC-4FB2-8D6F-06369C70BB4A/Library/Caches/AppLogs

// Case 2, invalid format
file://var/mobile/Containers/Data/Application/5FB2CD2D-91DC-4FB2-8D6F-06369C70BB4A/Library/Caches/AppLogs

dataPathにプレフィックスが付いている場合(例:file://)、それは無効です。


NSURLのインスタンスの場合、pathcase 1のような文字列を返し、absolutePathcase 2のような文字列を返します。

4
AechoLiu

私の場合、513エラーの意味はまだ完全にはわかりませんが、[NSFileHandle fileHandleForReadingFromURL:theUrl error:&err ]を使用して開いたファイルのURLを読み取ろうとしたときにエラーが発生していました。

この回答 から、iOS 13では、アプリで開かれている外部ファイルにアクセスするためにstartAccessingSecurityScopedResourceを使用する必要があることに気付きました。次のようにファイル呼び出しをラップすると、エラー513の発生が停止しました。

if( [myURL startAccessingSecurityScopedResource] ) 
{
    NSFileHandle* myFile = [NSFileHandle fileHandleForReadingFromURL:myURL error:&err ];
    // ...Do file reads here...
    [theUrl stopAccessingSecurityScopedResource];
}
0
Paul Slocum