从锁定屏幕处理本地操作时无法从 iOS 应用程序沙箱中读取

Can't read from iOS app sandbox when handling local action from lock screen

为了处理本地操作,我的应用需要读取文件来决定要做什么。当本地操作来自与横幅或警报交互的用户时,这很好用。当本地操作来自用户与锁定屏幕上的通知交互时,只要应用程序当前处于后台(而不是完全关闭),它也适用。

但是,如果应用完全关闭,并且用户尝试与锁定屏幕上的通知进行交互,我会收到一条错误消息

"The file ... couldn’t be opened because you don’t have permission to view it."

有谁知道可能出了什么问题,在这种情况下我该如何访问以前保存的文件?

例如,以下代码可以正常工作,除非由于锁定屏幕上的通知而调用 handleActionWithIdentifier,并且应用已关闭。

// Handle local actionable notifications
- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier forLocalNotification: (UILocalNotification *) notification completionHandler: (void (^)()) completionHandler
{
    //NSString *test = @"hello world";
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:@"test"];
    //[test writeToFile:appFile atomically:YES encoding:NSUTF8StringEncoding error:nil];

    NSLog(@"*********************");
    NSLog(@"trying to read test from handle action");
    NSLog(@"trying to read test from this location: %@", appFile);
    NSError *testerror;
    NSStringEncoding testencoding;
    NSString *testString = [NSString stringWithContentsOfFile:appFile usedEncoding:&testencoding error:&testerror];
    if (testerror) {
        NSLog(@"Failed to read storage file: %@", testerror);
    } else if (testencoding != NSUTF8StringEncoding) {
        NSLog(@"Incorect encoding of storage file.");
    } else {
        NSLog(testString);
    }
    NSLog(@"*********************");
}

错误发生时上述代码的完整输出如下:

Aug 11 14:39:42 iPhone Tandem[614] <Warning>: *********************
Aug 11 14:39:42 iPhone Tandem[614] <Warning>: trying to read test from handle action
Aug 11 14:39:42 iPhone Tandem[614] <Warning>: trying to read test from this location: /var/mobile/Containers/Data/Application/2C31417E-EF8E-4E0A-AC37-F4CB5BE9A4A5/Documents/test
Aug 11 14:39:42 iPhone Tandem[614] <Warning>: Failed to read storage file: Error Domain=NSCocoaErrorDomain Code=257 "The file “test” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/2C31417E-EF8E-4E0A-AC37-F4CB5BE9A4A5/Documents/test, NSUnderlyingError=0x145577d30 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
Aug 11 14:39:42 iPhone Tandem[614] <Warning>: *********************

如果我也尝试从 application: didFinishLaunching: 读取文件,也会出现同样的问题。

您应该检查文件保护属性。我的猜测是它被设置为 NSFileProtectionCompleteNSFileProtectionCompleteUnlessOpen 这意味着当设备被锁定时无法读取文件。您可以将属性设置为 NSFileProtectionNone 以在设备锁定时读取文件,但请注意它不会以加密状态存储。

参见:https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/#//apple_ref/doc/constant_group/File_Protection_Values