文件提供商应用扩展程序出错

时间:2015-02-13 09:50:34

标签: ios ios8

我正在为我的文档管理应用程序开发开放模式的应用扩展程序。我已经实现了正常工作的导入模式。但在开放模式下,当第三方应用程序尝试从我的存储提供程序打开任何文档时,文件提供程序的以下方法正在执行多次,这是一种无限执行,从而导致内存警告异常。

- (instancetype)init
- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler

同样供您参考完整的代码文件提供程序如下

- (NSFileCoordinator *)fileCoordinator {

    NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];

    [fileCoordinator setPurposeIdentifier:[self providerIdentifier]];

    return fileCoordinator;

}



- (instancetype)init {

    self = [super init];

    if (self) {

        [self.fileCoordinator coordinateWritingItemAtURL:[self documentStorageURL] options:0 error:nil byAccessor:^(NSURL *newURL) {

            // ensure the documentStorageURL actually exists

            NSError *error = nil;

            [[NSFileManager defaultManager] createDirectoryAtURL:newURL withIntermediateDirectories:YES attributes:nil error:&error];

        }];

    }

    return self;

}



- (void)providePlaceholderAtURL:(NSURL *)url completionHandler:(void (^)(NSError *error))completionHandler {

    // Should call + writePlaceholderAtURL:withMetadata:error: with the placeholder URL, then call the completion handler with the error if applicable.

    NSString* fileName = [url lastPathComponent];



    NSURL *placeholderURL = [NSFileProviderExtension placeholderURLForURL:[self.documentStorageURL URLByAppendingPathComponent:fileName]];



    NSUInteger fileSize = 0;

    // TODO: get file size for file at <url> from model



    [self.fileCoordinator coordinateWritingItemAtURL:placeholderURL options:0 error:NULL byAccessor:^(NSURL *newURL) {



        NSDictionary* metadata = @{ NSURLFileSizeKey : @(fileSize)};

        [NSFileProviderExtension writePlaceholderAtURL:placeholderURL withMetadata:metadata error:NULL];

    }];

    if (completionHandler) {

        completionHandler(nil);

    }

}



- (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

    NSError* error = nil;

    __block NSError* fileError = nil;

    //getting the actual fiile from the shared container

    NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.company.test.NBox"];

    storeURL = [storeURL URLByAppendingPathComponent:[url.path lastPathComponent]];



    NSData* fileData = [NSData dataWithContentsOfFile:[storeURL path]];

    // TODO: get the contents of file at <url> from model


     //Writing the file data to the documentStorage location

    //[self.fileCoordinator coordinateWritingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {

        [fileData writeToURL:url options:0 error:&fileError];

    //}];

    if (error!=nil) {

        completionHandler(error);

    } else {

        completionHandler(fileError);

    }

}



- (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; kick off update process

    NSLog(@"Item changed at URL %@", url);

}



- (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.

    // Care should be taken that the corresponding placeholder file stays behind after the content file has been deleted.



    [self.fileCoordinator coordinateWritingItemAtURL:url options:NSFileCoordinatorWritingForDeleting error:NULL byAccessor:^(NSURL *newURL) {

        [[NSFileManager defaultManager] removeItemAtURL:newURL error:NULL];

    }];

    [self providePlaceholderAtURL:url completionHandler:NULL];

}

谢谢, VSH

1 个答案:

答案 0 :(得分:1)

我也在尝试为开放模式开发应用扩展程序。我还没有成功,但我没有得到无限的执行。查看代码,storeURL中的startProvidingItemAtURL:可能指向容器内的某些内容。如果是这样,那么对fileData的赋值将触发无限递归。

作为测试,请尝试使用以下测试消息设置fileData

NSString *message = [NSString stringWithFormat:@"This is a test."];
NSData *fileData = [NSKeyedArchiver archivedDataWithRootObject:message];

如果可以,那么storeURL会出现问题,您必须找出一些不同的位置来获取数据。

(顺便提一下,我注意到你在startProvidingItemAtURL:注释掉了文件协调员。我最后还是这样做是为了防止死锁,因为文档中有一条说明“不要使用文件协调”在这个方法中。“但它很混乱,因为文件提供者的模板代码将文件协调器放在该方法中!”