简体   繁体   English

iOS模拟器未将“文件”应用显示为NSFileproviderExtension的选项

[英]iOS Simulator doesn't show Files app as option for NSFileproviderExtension

I'm having some trouble with getting my app to show up as a location in the iOS 11 files app. 我的应用程序无法在iOS 11文件应用程序中显示为某个位置时遇到问题。 I added an NSFileproviderExtension . 我添加了NSFileproviderExtension However, when I run it I only get safari and some other apps as an option. 但是,当我运行它时,我只能选择使用野生动物园和其他一些应用程序。 When I select safari, then close safari, open Files, it does show my extension, but when I click anything it crashes. 当我选择野生动物园,然后关闭野生动物园,打开文件时,它的确显示了我的扩展名,但是当我单击任何内容时,它就会崩溃。 Any ideas for the best way to do this? 有最佳方​​法的想法吗? Any good tutorials? 有什么好的教程吗?

@interface FileProviderExtension ()

@property (nonatomic, readonly, strong) NSFileManager *fileManager;

@end

@implementation FileProviderExtension

- (instancetype)init {
    if (self = [super init]) {
        _fileManager = [[NSFileManager alloc] init];
    }
    return self;
}

- (nullable NSFileProviderItem)itemForIdentifier:(NSFileProviderItemIdentifier)identifier error:(NSError * _Nullable *)error {
    // resolve the given identifier to a record in the model

    // TODO: implement the actual lookup
    NSFileProviderItem item = nil;

    return item;
}

- (nullable NSURL *)URLForItemWithPersistentIdentifier:(NSFileProviderItemIdentifier)identifier {
    // resolve the given identifier to a file on disk
    NSFileProviderItem item = [self itemForIdentifier:identifier error:NULL];
    if (!item) {
        return nil;
    }

    // in this implementation, all paths are structured as <base storage directory>/<item identifier>/<item file name>
    NSFileProviderManager *manager = [NSFileProviderManager defaultManager];
    NSURL *perItemDirectory = [manager.documentStorageURL URLByAppendingPathComponent:identifier isDirectory:YES];

    return [perItemDirectory URLByAppendingPathComponent:item.filename isDirectory:NO];
}

- (nullable NSFileProviderItemIdentifier)persistentIdentifierForItemAtURL:(NSURL *)url {
    // resolve the given URL to a persistent identifier using a database
    NSArray <NSString *> *pathComponents = [url pathComponents];

    // exploit the fact that the path structure has been defined as
    // <base storage directory>/<item identifier>/<item file name> above
    NSParameterAssert(pathComponents.count > 2);

    return pathComponents[pathComponents.count - 2];
}

- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler {
    // Should ensure that the actual file is in the position returned by URLForItemWithIdentifier:, then call the completion handler

    /* TODO:
     This is one of the main entry points of the file provider. We need to check whether the file already exists on disk,
     whether we know of a more recent version of the file, and implement a policy for these cases. Pseudocode:

     if (!fileOnDisk) {
         downloadRemoteFile();
         callCompletion(downloadErrorOrNil);
     } else if (fileIsCurrent) {
         callCompletion(nil);
     } else {
         if (localFileHasChanges) {
             // in this case, a version of the file is on disk, but we know of a more recent version
             // we need to implement a strategy to resolve this conflict
             moveLocalFileAside();
             scheduleUploadOfLocalFile();
             downloadRemoteFile();
             callCompletion(downloadErrorOrNil);
         } else {
             downloadRemoteFile();
             callCompletion(downloadErrorOrNil);
         }
     }
     */

    completionHandler([NSError errorWithDomain:NSCocoaErrorDomain code:NSFeatureUnsupportedError userInfo:@{}]);
}


- (void)itemChangedAtURL:(NSURL *)url {
    // Called at some point after the file has changed; the provider may then trigger an upload

    /* TODO:
     - mark file at <url> as needing an update in the model
     - if there are existing NSURLSessionTasks uploading this file, cancel them
     - create a fresh background NSURLSessionTask and schedule it to upload the current modifications
     - register the NSURLSessionTask with NSFileProviderManager to provide progress updates
     */
}

- (void)stopProvidingItemAtURL:(NSURL *)url {
    // Called after the last claim to the file has been released. At this point, it is safe for the file provider to remove the content file.

    // TODO: look up whether the file has local changes
    BOOL fileHasLocalChanges = NO;

    if (!fileHasLocalChanges) {
        // remove the existing file to free up space
        [[NSFileManager defaultManager] removeItemAtURL:url error:NULL];

        // write out a placeholder to facilitate future property lookups
        [self providePlaceholderAtURL:url completionHandler:^(NSError * __nullable error) {
            // TODO: handle any error, do any necessary cleanup
        }];
    }
}

#pragma mark - Actions

/* TODO: implement the actions for items here
 each of the actions follows the same pattern:
 - make a note of the change in the local model
 - schedule a server request as a background task to inform the server of the change
 - call the completion block with the modified item in its post-modification state
 */

#pragma mark - Enumeration

- (nullable id<NSFileProviderEnumerator>)enumeratorForContainerItemIdentifier:(NSFileProviderItemIdentifier)containerItemIdentifier error:(NSError **)error {
    id<NSFileProviderEnumerator> enumerator = nil;
    if ([containerItemIdentifier isEqualToString:NSFileProviderRootContainerItemIdentifier]) {
        // TODO: instantiate an enumerator for the container root
    } else if ([containerItemIdentifier isEqualToString:NSFileProviderWorkingSetContainerItemIdentifier]) {
        // TODO: instantiate an enumerator for the working set
    } else {
        // TODO: determine if the item is a directory or a file
        // - for a directory, instantiate an enumerator of its subitems
        // - for a file, instantiate an enumerator that observes changes to the file
    }

    return enumerator;
}

@end

For some reason Xcode won't show the Files app to debug your NSFileproviderExtension . 由于某些原因,Xcode不会显示“文件”应用程序来调试您的NSFileproviderExtension

To test it anyway just choose any other app, search for the Share button in that app and then choose Files in the share screen. 无论如何要测试它,只需选择任何其他应用程序,在该应用程序中搜索“共享”按钮,然后在共享屏幕中选择“文件”。 You can also dismiss the app and go to Files where your extension will show app and get debugged (breakpoints, console messages, etc.). 您也可以关闭应用程序,然后转到扩展名将显示应用程序并进行调试的文件(断点,控制台消息等)。

As for the crash, add an Exception Breakpoint to stop at the line of code responsible for the crash (as you would do when debugging your main program). 至于崩溃,添加一个异常断点以停止导致崩溃的代码行(就像调试主程序时那样)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM