Cocoa - 如何检测泛在容器中的变化

Posted

技术标签:

【中文标题】Cocoa - 如何检测泛在容器中的变化【英文标题】:Cocoa - How to detect change in ubiquity container 【发布时间】:2013-06-14 20:55:44 【问题描述】:

我有一个 OS X 应用程序通过一个普遍存在的容器来回同步单个文档到一个 ios 等效应用程序。 iOS 应用程序在 Mac 端发生变化时接收数据,并在 iOS 端发生变化时发送数据(因此 iOS 应用程序正在运行),Mac 应用程序在 Mac 端发生变化时发送数据,并且在启动应用程序时接收数据,但它似乎在运行时没有再次检查任何数据。我希望它能够立即自动更新任何更改,就像 OS X“Notes”应用程序根据 iOS 端的更改所做的那样。

在启动时,这是被调用的相关函数:

+(NSMutableDictionary *)getAllNotes 
    if(allNotes == nil) 
        allNotes = [[NSMutableDictionary alloc]initWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey:kAllNotes]];

        cloudDoc = [[CloudDocument alloc]initWithContentsOfURL:[self notesURL] ofType:NSPlainTextDocumentType error:nil];
        [cloudDoc saveToURL:[self notesURL] ofType:NSPlainTextDocumentType forSaveOperation:NSSaveOperation error:nil];
    
    return allNotes;

“CloudDocument”类(NSDocument 的子类)包括:

#import "Data.h"

@implementation CloudDocument

-(NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError 
    return [NSKeyedArchiver archivedDataWithRootObject:[Data getAllNotes]];


-(BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError 
    NSDictionary *dict = (NSDictionary *)[NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)data];
    [Data didReceiveCloudData:dict];
    return YES;


+(BOOL)autosavesInPlace 
    return YES;


@end

这又回到了:

+(void)didReceiveCloudData:(NSDictionary *)d 
    allNotes = [[NSMutableDictionary alloc]initWithDictionary:d];
    [[NSUserDefaults standardUserDefaults] setObject:allNotes forKey:kAllNotes];

    [cloudDoc updateChangeCount:NSChangeDone];

我认为问题在于我的代码中没有任何部分相当于“定期检查无处不在的容器是否已更改,然后执行...”等短语。我是肯定有一个众所周知的过程(NSDocument 中的一些通知事件或其他东西),但我已经四处搜索,我发现的所有东西都是针对 iOS/UIDocuments 而不是 OS X/NSDocuments,或者这都是理论和结束我的头没有任何有形的代码示例来梳理和挑选。

谁能帮我注册一个 iCloud 文档在 ubiquity 容器中发生变化的方法,最好把它放在哪里(AppDelegate、CloudDocument.m 等)?我只有一个文件在同步,由常量kAllNotes 表示,所以我不需要跟踪一堆不同的文件或任何东西。我很确定我可以使用在启动时运行的代码来做需要做的事情,我只是不知道该怎么做才能启动自动同步过程。

提前谢谢你!

PS 我还是个初学者,所以非常感谢教程和代码示例。

【问题讨论】:

【参考方案1】:

您正在寻找 NSMetadataQuery - 它可以像聚光灯一样持续运行搜索任何类型的文件 - 并且在 iOS 和 OS X 上都可用(实际上在 iOS 上它只能用于观察无处不在的变化容器)。我没有任何关于如何使用它的链接 - Apple 文档太笼统,最初没有多大意义,但是在“NSMetadataQuery iCloud”上进行搜索,你应该被排序 - 关于这个主题有大量信息.

使用 NSMetadataQuery 时,您会在观察到的文件夹系统中的某些内容发生更改时收到通知,并且它不仅适用于 UIDocument 文件,即使很多示例都担心 UIDocuments。

【讨论】:

谢谢!我可以要求澄清一下:我会在 CloudDocument 对象(从 NSDocument 子类化)的初始化方法中设置 NSMetadataQuery 吗?或者我在 applicationDidFinishLaunching 中做,还是什么?我是 NSMetadataQuery、Notifications 和所有这些东西的新手,因此非常感谢您在设置它们时提供的任何建议。 随心所欲。在我的应用程序上,我在使用 URLForUbiquityContainerIdentifier: 确定了无处不在的 URL 后创建它,并且仅当用户打开了 iCloud 时才创建它。这是有道理的,因为如果您没有有效的通用 URL,则设置查询毫无意义。有上百万种不同的方法来解决这个问题,只需选择对您的应用程序感觉更自然的方式。我倾向于有一个“CloudController”对象,它观察无处不在的容器中发生的事情,并对用户注销、云可用性等做出反应,我在其中放置了我的元数据查询。 谢谢!如果您有时间(和意愿),您能否就这个话题发表评论another question I posted?另一位用户一直在帮助我,但是已经开发了一个评论线程,我正试图准确找出剩余的问题是什么。据我了解,除了不知道文件扩展名之外,我的所有代码都已正确设置,但也可能存在另一个问题。我非常接近完成这个应用程序,我可以品尝它。再次感谢您的帮助!【参考方案2】:

确实是 NSMetadataQuery - 感觉就像是 hack,但似乎是监控标准(非 UIDocument)文件更改的唯一方法。

这是我编译的示例项目。它允许您从相机胶卷上传图像,然后监控无处不在的 Documents 文件夹的更改:

https://github.com/versluis/iCloud-Images

【讨论】:

以上是关于Cocoa - 如何检测泛在容器中的变化的主要内容,如果未能解决你的问题,请参考以下文章

检测屏幕方向变化(快速)

如何检测 SwiftUI 中的 @Published 值发生了啥变化?

检测视频分辨率变化

Cocoa 中的 FNSubscribe 替换

如何检测 Amazon S3 中的变化? [复制]

如何检测 Angular 中的 @Input() 值何时发生变化?