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

How do you use a class method to distribute multiple shared instances of UIManagedDocument?

我有一个助手类,用于分发uimanageddocument的共享实例。其思想是,用户为磁盘上的特定文件请求uimanageddocument共享实例。在这种情况下,它是一个核心数据存储。如果用户请求位于不同路径的核心数据存储,我希望为该文件分发uimanageddocument实例。

我的问题是:是否可以创建uimanageddocument的新实例,并在文件更改时将其分配给静态变量?例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+ (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的一个实例,因此在核心数据存储中有多个写入程序的情况下,我不必经常保持更改的同步。但是,由于磁盘上有多个核心数据存储,所以我不能每次只分发相同的静态变量。

有什么想法吗?即使是如何处理这个设计问题,我也非常坚持…感谢您的帮助。

谢谢-卫国明


好吧,如果你想做我认为你想做的事:不,这行不通。

我假设您希望为所请求的磁盘上的每个唯一文件保留一个sharedDocument,独立于现有的任何其他sharedDocuments。但您的代码不会这样做,因为每次传入的文件名与上次传入的文件名不同时,对旧UIManagedDocument的引用都会丢失。

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

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

您希望docAdocA2是同一个UIManageDocument,但这不会发生,因为中间一行导致静态变量忘记了file1.txt1的原始管理文档。

我将放弃使用静态变量。还有很多其他方法可以做到这一点。一种简单的方法是使用NSMutableDictionary将文件名映射到UIManagedDocument实例。像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+ (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文件中声明它,如下所示:

1
2
3
static NSMutableDictionary *docDictionary = nil;

@implementation MyClass ...

这实际上提供了一个单独的docDictionary实例,该实例存在于类的任何实例之外。不过,类的实例仍然可以访问它。

static关键字确保不能在当前编译单元(即源文件)之外访问该docDictionary变量。有关静态及其更多不同含义的更多信息,请参见C++中的静态与静态之间的区别等问题。?


我明白了。使用setobject,而不是addobject。