【问题标题】:Setting up NSMetadataQueryDidUpdateNotification for a simple response为简单响应设置 NSMetadataQueryDidUpdateNotification
【发布时间】:2013-06-12 08:52:12
【问题描述】:

我正在尝试在 OS X 应用程序上使用NSMetadataQueryDidUpdateNotification 启动并运行,以便在我的 iCloud 通用容器中的文件更新时提醒我。我一直在做很多研究(包括阅读其他 Stack 答案,如 thisthisthisthis),但我似乎仍然不太正确。

我有一个从 NSDocument 子类化的“CloudDocument”对象,它在 H: 中包含此代码:

@property (nonatomic, strong) NSMetadataQuery *alertQuery;

这是M文件:

@synthesize alertQuery;

-(id)init {
    self = [super init];
    if (self) {
        if (alertQuery) {
            [alertQuery stopQuery];
        } else {
            alertQuery = [[NSMetadataQuery alloc]init];
        }

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidUpdate:) name:NSMetadataQueryDidUpdateNotification object:nil];
        NSLog(@"Notification created");

        [alertQuery startQuery];
    }
    return self;
}

-(void)queryDidUpdate:(NSNotification *)notification {
    NSLog(@"Something changed!!!");
}

根据我的最佳理解,如果一个预先存在的查询正在运行,那么它应该停止一个预先存在的查询,设置一个对无处不在容器的更改的通知,然后启动查询,以便它从这里开始监视更改。

除了,显然不是这样,因为我在启动登录时得到Notification created,但在我更改 iCloud 文档时从未得到Something changed!!!

谁能告诉我我错过了什么?如果你超级棒,你会帮我提供一些代码示例和/或教程吗?

编辑:如果它很重要/有帮助,我的 ubiquity 容器中只有一个文件正在同步。它被称为“笔记”,所以我使用来自以下位置的 URL 结果访问它:

+(NSURL *)notesURL {
    NSURL *url = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    return [url URLByAppendingPathComponent:kAllNotes];
}

其中“kAllNotes”设置为#define kAllNotes @"notes"

编辑#2:通过我与 Daij-Djan 的对话,我的代码有很多更新,所以这是我的更新代码:

@synthesize alertQuery;

-(id)init {
    self = [super init];
    if (self) {
        alertQuery = [[NSMetadataQuery alloc] init];
        if (alertQuery) {
            [alertQuery setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];

            NSString *STEDocFilenameExtension = @"*";
            NSString* filePattern = [NSString stringWithFormat:@"*.%@", STEDocFilenameExtension];
            [alertQuery setPredicate:[NSPredicate predicateWithFormat:@"%K LIKE %@", NSMetadataItemFSNameKey, filePattern]];
        }

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidUpdate:) name:NSMetadataQueryDidFinishGatheringNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidUpdate:) name:NSMetadataQueryDidUpdateNotification object:nil];

        NSLog(@"Notification created");

        [alertQuery startQuery];
    }
    return self;
}

-(void)queryDidUpdate:(NSNotification *)notification {
    [alertQuery disableUpdates];

    NSLog(@"Something changed!!!");

    [alertQuery enableUpdates];
}

【问题讨论】:

    标签: xcode cocoa icloud nsmetadataquery


    【解决方案1】:

    你如何保存你的文档——你给它的网址是什么?除非你自己给它一个扩展名,否则它不会自动被赋予一个 - 所以你的*.* 模式永远不会匹配没有扩展名的文件。试试* 作为模式,看看会发生什么。

    此外,它还有助于记录 queryDidUpdate 中发生的事情,直到您弄清楚发生了什么:

    尝试类似:

    -(void)queryDidUpdate:(NSNotification *)notification {
        [alertQuery disableUpdates];
    
        NSLog(@"Something changed!!!");
    
        // Look at each element returned by the search
        // - note it returns the entire list each time this method is called, NOT just the changes
        int resultCount = [alertQuery resultCount];
        for (int i = 0; i < resultCount; i++) {
            NSMetadataItem *item = [alertQuery resultAtIndex:i];
            [self logAllCloudStorageKeysForMetadataItem:item];
        }
    
        [alertQuery enableUpdates];
    }
    
    - (void)logAllCloudStorageKeysForMetadataItem:(NSMetadataItem *)item
    {
        NSNumber *isUbiquitous = [item valueForAttribute:NSMetadataItemIsUbiquitousKey];
        NSNumber *hasUnresolvedConflicts = [item valueForAttribute:NSMetadataUbiquitousItemHasUnresolvedConflictsKey];
        NSNumber *isDownloaded = [item valueForAttribute:NSMetadataUbiquitousItemIsDownloadedKey];
        NSNumber *isDownloading = [item valueForAttribute:NSMetadataUbiquitousItemIsDownloadingKey];
        NSNumber *isUploaded = [item valueForAttribute:NSMetadataUbiquitousItemIsUploadedKey];
        NSNumber *isUploading = [item valueForAttribute:NSMetadataUbiquitousItemIsUploadingKey];
        NSNumber *percentDownloaded = [item valueForAttribute:NSMetadataUbiquitousItemPercentDownloadedKey];
        NSNumber *percentUploaded = [item valueForAttribute:NSMetadataUbiquitousItemPercentUploadedKey];
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
    
        BOOL documentExists = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];
    
        NSLog(@"isUbiquitous:%@ hasUnresolvedConflicts:%@ isDownloaded:%@ isDownloading:%@ isUploaded:%@ isUploading:%@ %%downloaded:%@ %%uploaded:%@ documentExists:%i - %@", isUbiquitous, hasUnresolvedConflicts, isDownloaded, isDownloading, isUploaded, isUploading, percentDownloaded, percentUploaded, documentExists, url);
    }
    

    【讨论】:

    • 查看上面的 notesURL,我认为 *.* 模式肯定会引起您的麻烦,因为您没有在文件名中添加扩展名。试试上面的NSString* filePattern = @"*";
    • 好的,事情是这样的:我插入了 Rob 提供的代码,并将 filePattern NSString 更改为只是一个星号。但是logAllCloudStorageKeysForMetadataItem 永远不会被调用,因为resultCount 是0。但是,当数据在启动时成功下载并在更改时上传时,这怎么可能呢?显然有些东西...要回答您关于我的 URL 的问题,我使用 NSURL *url = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; return [url URLByAppendingPathComponent:kAllNotes];,其中 "kAllNotes" = "notes"。
    • 使用developer.icloud.com 查看实际上传到 iCloud 的文件。实际上,我刚刚注意到,您的 URL 将在 ubiquity 容器的根目录中创建文件 - 但您的查询搜索范围设置为 NSMetadataQueryUbiquitousDocumentsScope - 这意味着它仅在 Documents/ 文件夹中搜索 - 您需要使用 NSMetadataQueryUbiquitousDataScope 搜索 Documents/ 之外的所有文件。通过此更改,您应该会发现每次在查询的定义搜索范围内更改文件时都会触发查询。
    • 天哪,我认为它在工作!!!!!!!每当我从 iOS 应用程序更改文件时,我都会收到更新。在这个功能上工作了四天,现在我认为它可能完成了。谢谢!!!!
    • 万岁!四天?这就是全部?你实际上做得很好! iCloud 从未像您刚开始时想象的那么简单......
    【解决方案2】:

    你永远不会分配你的 alertQuery....

    你需要分配的地方,为它初始化一个 NSMetaDataQuery

    示例


    NSMetadataQuery* aQuery = [[NSMetadataQuery alloc] init];
    if (aQuery) {
        // Search the Documents subdirectory only.
        [aQuery setSearchScopes:[NSArray
                    arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
    
        // Add a predicate for finding the documents.
        NSString* filePattern = [NSString stringWithFormat:@"*"];
        [aQuery setPredicate:[NSPredicate predicateWithFormat:@"%K LIKE %@",
                    NSMetadataItemFSNameKey, filePattern]];
    
       // Register for the metadata query notifications.
       [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(processFiles:)
            name:NSMetadataQueryDidFinishGatheringNotification
            object:nil];
       [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(processFiles:)
            name:NSMetadataQueryDidUpdateNotification
            object:nil];
    
       // Start the query and let it run.
       [aQuery startQuery];
    

    }

    processFiles 方法

    == 你的 queryDidUpdate

    - processFiles(NSNotification*)note {
         [aQuery disableUpdates];
    
         .....
    
         [aQuery enableUpdates];
    }
    

    注意:在此处禁用和重新启用搜索!

    见:

    http://developer.apple.com/library/ios/#documentation/General/Conceptual/iCloud101/SearchingforiCloudDocuments/SearchingforiCloudDocuments.html

    【讨论】:

    • 太好了,谢谢!我开始明白一切,但我遇到了一个错误:Use of undeclared identifier "STEDocFilenameExtension". 这是我应该预先声明的东西还是什么?您附加的链接似乎将其视为给定的,尽管该文章适用于 iOS 而不是 OS X。是否有 Cocoa 的等价物,或我可以采取的其他步骤?
    • 我从here 得知他们只是将STEDocFilenameExtension 设置为“stedoc”,所以我也这样做了。该代码现在没有错误,并且与您附加的链接中的演练密切匹配,但它仍然无法正常工作......(再次感谢您帮助我,我知道我目前很noobish。)
    • stedoc 可能只对他们的文件有效。您应该将其设置为您用于文件的扩展名
    • 好的,所以“DidFinishGatheringNotification”行在启动时调用queryDidUpdate,但再也不会调用了。在我未受过教育的观点中,这是因为我不知道我使用的是什么文件扩展名,因为我是新手并且使用了大量的教程代码。是否有默认扩展名或查找方法?我有像[NSKeyedArchiver archivedDataWithRootObject:[Data getAllNotes]];[cloudDoc saveToURL:[self notesURL] ofType:NSPlainTextDocumentType forSaveOperation:NSSaveOperation error:nil];[url URLByAppendingPathComponent:@"notes"]; 这样的行,但我不知道该怎么做。
    • 嗯。我已经循环浏览了我能想到的每个主要文件扩展名(例如 plist、txt、dat、data 等),以及我可以通过在线搜索找到的每个文件,我什至尝试将扩展名保留为星号希望它将适用于所有文件类型的所有文件(因为我只有一个我正在更改的文件),但我无法得到回应。每次,它都会在启动时调用 queryDidUpdate 方法 1-3 次,然后再也不会。有什么想法吗?或者文件扩展名不是我的主要问题? (PS再次感谢您的帮助!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 2023-03-25
    • 2021-09-08
    • 1970-01-01
    • 2013-10-06
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多