如何使用类方法分发多个共享的UIManagedDocument实例?

4
我有一个辅助类,用于分发UIManagedDocument的共享实例。其思想是用户请求特定磁盘上的UIManagedDocument共享实例。在这种情况下,它是一个核心数据存储库。如果用户请求位于不同路径的核心数据存储库,则我希望为该文件分发UIManagedDocument的实例。
我的问题是:当文件更改时,创建新的UIManagedDocument实例并将其分配给静态变量是否可以?例如:
+ (UIManagedDocument *)sharedManagedDocumentForFile:(NSString *)fileName
{
    static UIManagedDocument *sharedDocument = nil;

    NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    url = [url URLByAppendingPathComponent:fileName];
    // url is "<Documents Directory>/<vacationName>"

    // Create the shared instance lazily upon the first request.
    if (sharedDocument == nil) {
        sharedDocument = [[UIManagedDocument alloc] initWithFileURL:url];
    }

    if (sharedDocument.fileURL != url) {
        UIManagedDocument *newDocument = [[UIManagedDocument alloc] initWithFileURL:url];
        sharedDocument = newDocument;
    }

    return sharedDocument;
}

基本上我要做的就是分发一个UIManagedDocument的实例,这样在有多个写入核心数据存储器的情况下,我不必不断地保持变化同步。然而,由于磁盘上有多个核心数据存储器,我不能每次都分发相同的静态变量。

有什么想法吗?我甚至不知道如何解决这个设计问题... 感谢任何帮助。

谢谢 - Jake


5
我相信这会带有强制性判决。 - PengOne
@Java V 我想他只是在开玩笑...哈哈 - bschultz
“ok”和“legal”具体指什么意思? - occulus
“Ok”的意思是,如果我更改静态变量所指向的内存地址,是否会遇到一些错误或问题。 - Joey J
2
这看起来不像是“shared”文档,而更像是“currentDocument”。如果是这样,请适当处理:在层次结构的较高位置(例如应用程序委托)中创建相应的属性,分别使用该属性并摆脱类方法和静态变量。 - Davyd Geyl
2个回答

6

如果你尝试做我认为你想做的事情,那么很遗憾,这种方法不起作用。

我猜你希望每个唯一的文件请求都可以持久化一个sharedDocument,与其他任何现有的sharedDocuments独立。但是,你的代码无法实现此目的,因为每次传入的文件名与上一次传入的文件名不同时,旧UIManagedDocument的引用就会丢失。

想象一下以下(人为制造的)场景:

UIManagedDocument *docA = [self sharedManagedDocumentForFile:@"fileA.txt"];
UIManagedDocument *docB = [self sharedManagedDocumentForFile:@"fileB.txt"];
UIManagedDocument *docA2 = [self sharedManagedDocumentForFile:@"fileA.txt"];

您希望docAdocA2是相同的UIManageDocument,但由于中间的代码使您的静态变量忘记了file1.txt1的原始托管文档,这将不会发生。

我建议放弃使用静态变量。还有许多其他方法可以实现此目的。一个简单的方法是使用NSMutableDictionary将文件名映射到UIManagedDocument实例。类似这样:

+ (UIManagedDocument *)sharedManagedDocumentForFile:(NSString *)fileName
{
    //assuming we have an instance variable:  NSMutableDictionary *docDictionary
    UIManagedDocument *doc = [docDictionary objectForKey:fileName];

    if (!doc) {
        NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        url = [url URLByAppendingPathComponent:fileName];
        // url is "<Documents Directory>/<vacationName>"

        doc = [[UIManagedDocument alloc] initWithFileURL:url];

        [docDictionary setObject:doc forKey:fileName];
    }
    return doc;
}

更新

由于sharedManagedDocumentForFile:是一个类方法,你不能将docDictionary作为你的类的实例变量存储,正如你所指出的那样。相反,你可以在你的.m文件中在你的类实现之前声明它,像这样:

static NSMutableDictionary *docDictionary = nil;

@implementation MyClass ...

这实际上提供了一个单独的docDictionary实例,该实例存在于类的任何实例之外。但是,您的类的实例仍然可以访问它。 static关键字确保此docDictionary变量无法在当前编译单元(即源文件)之外访问。有关静态变量及其多种不同含义的更多信息,请参见诸如Difference between static in C and static in C++??之类的问题。

Occulus - 感谢您的回复。您提出的解决方案是更好的解决方法,因为您用例子解释了原因。但有一件事我不太明白。如果 sharedManagedDocumentForFile 是一个类方法,我们怎么访问实例变量 docDictionary 呢? - Joey J
好问题。我正在更新我的答案。 - occulus
谢谢!我已经实现了这个功能,看起来完美无缺。 - Joey J
请将 addObject 改为 setObject。 - Shmidt

0
我已经想通了。使用setObject而不是addObject。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接