NSMetadataQuery找不到iCloud文件

edo*_*o42 6 cocoa objective-c icloud

我按照Apple Docs NSMetadataQuery中的描述使用来搜索我的iCloud文件.我只有一个文件,我知道它的名字.我的问题是,有时这个文件不存在(我想因为它尚未下载),NSMetadataQuery无法找到它.

曾试图强行下载,NSFileManager startDownloadingUbiquitousItemAtURL:error:它给我一个错误.(阅读编辑)

我的解决方案是我第一次创建文件,然后我猜它存在,我用UIDocument打开它.但它可能不存在,或者可能是用户第一次打开应用程序.我无法确定这些事情.我的第一个问题是:如果UIDocument打开文件,则意味着它在某个地方找到了该文件.如果它不存在,它怎么能使用该文件?

然后,第二个问题:如果我的应用程序必须管理多个文件或名称未知的文件.如果NSMetadataQuery不起作用,我怎么能找到它们.

编辑: 如果startDownloadingUbiquitousItemAtURL应该用于开始下载文件,我怎么知道文件何时完成下载(可能有通知)?但是,更重要的是:如果总是说(删除原始名称),我如何下载文件?

   Error Domain=NSPOSIXErrorDomain Code=2 "The operation couldn’t be completed.
    No such file or directory" UserInfo=0x166cb0 {
    NSDescription=Unable to get real path for Path
'/private/var/mobile/Library/Mobile Documents/teamid~com~team~app/Documents/file.extension'
    }
Run Code Online (Sandbox Code Playgroud)

n.e*_*ind 7

我建议iCloud文件的以下加载例程.它涉及4个步骤:

  1. 首先,测试iCloud是否可访问
  2. 然后寻找你的文件(要么寻找你指定的特定文件,要么查找具有特定扩展名的所有文件,如*.txt,或者如果你真的不知道你正在寻找什么文件扩展名,那么NSPredicate *pred = [NSPredicate predicateWithFormat:@"NOT %K.pathExtension = '.'", NSMetadataItemFSNameKey];会返回所有文件有扩展名,如jpg,txt,dat等)
  3. 然后检查查询是否完成,以及
  4. 最后尝试加载文件.如果该文件不存在,请创建它.如果确实存在,请加载它.

以下是代表这四个步骤的代码:

    - (void)loadData:(NSMetadataQuery *)query {

    // (4) iCloud: the heart of the load mechanism: if texts was found, open it and put it into _document; if not create it an then put it into _document

    if ([query resultCount] == 1) {
        // found the file in iCloud
        NSMetadataItem *item = [query resultAtIndex:0];
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:url];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc openWithCompletionHandler:^(BOOL success) {
            if (success) {
                NSLog(@"AppDelegate: existing document opened from iCloud");
            } else {
                NSLog(@"AppDelegate: existing document failed to open from iCloud");
            }
        }];
    } else {
        // Nothing in iCloud: create a container for file and give it URL
        NSLog(@"AppDelegate: ocument not found in iCloud.");

        NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
        NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:@"text.txt"];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:ubiquitousPackage];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc saveToURL:[doc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            NSLog(@"AppDelegate: new document save to iCloud");
            [doc openWithCompletionHandler:^(BOOL success) {
                NSLog(@"AppDelegate: new document opened from iCloud");
            }];
        }];
    }
}

- (void)queryDidFinishGathering:(NSNotification *)notification {

    // (3) if Query is finished, this will send the result (i.e. either it found our text.dat or it didn't) to the next function

    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];

    [self loadData:query];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
    _query = nil; // we're done with it
}

-(void)loadDocument {

    // (2) iCloud query: Looks if there exists a file called text.txt in the cloud

    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
    _query = query;
    //SCOPE
    [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
    //PREDICATE
    NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, @"text.txt"];
    [query setPredicate:pred];
    //FINISHED?
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
    [query startQuery];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"AppDelegate: app did finish launching");
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil] autorelease];
    } else {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil] autorelease];
    }

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    // (1) iCloud: init

    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (ubiq) {
        NSLog(@"AppDelegate: iCloud access!");
        [self loadDocument];
    } else {
        NSLog(@"AppDelegate: No iCloud access (either you are using simulator or, if you are on your phone, you should check settings");
    }


    return YES;
}
Run Code Online (Sandbox Code Playgroud)