【问题标题】:Opening UIDocument in a loop循环打开 UIDocument
【发布时间】:2014-04-13 13:55:19
【问题描述】:

我正在尝试使用- (void)openWithCompletionHandler:(void (^)(BOOL success))completionHandler 循环打开多个UIDocument 实例。

确切地说,我正在从文档文件夹加载一个文件列表,每个文件代表一个可以登录到我的应用程序的用户。现在,显然我想在所有用户/UIDocument 打开之后显示我的登录对话框。不幸的是,我似乎无法为此提出一个好的方法。我所拥有的是:

 -(void)reloadUsers
 {
     __block int cnt= 0;

     NSArray* localDocuments = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[AppDelegate localDocumentsDirectoryURL] path] error:nil];

     for (NSString* document in localDocuments)
     {
        if (![document hasSuffix:@".user"])
           continue;

        // User beeing UIDocument subclass

        User* user=[[[User alloc] initWithFileURL:[NSURL fileURLWithPath:[[[AppDelegate localDocumentsDirectoryURL] path]
                                                                       stringByAppendingPathComponent:document]]] autorelease];

        NSLog(@"Opening user document at url '%@'/'%@' ...", [AppDelegate localDocumentsDirectoryURL], document);

        [user openWithCompletionHandler:^(BOOL success)
        {
           [self.userList addObject:user];

           cnt++;
        }];
     }

     NSLog(@"Loaded %d local users", cnt);
  }

问题 1:最后的 NSLog 是否会工作并显示实际加载的用户数,还是因为cnt++ 是异步完成的,所以它是一个随机值?

问题 2:如何更改上述功能,以便安全地执行以下操作:

 {   // app finished loading

    [MyClass reloadUsers];

    [LoginDialog show];    // this shall happen AFTER reloadUsers has loaded ALL documents
 }

【问题讨论】:

  • 您可以使用委托方法。当cnt(实际上,在博客中做NSLog可能更好理解)等于您要打开的文件数时,您可以告诉您的对象做[LoginDialog show]。并不是说在您的块中您应该阅读success bool 值。
  • 我找到了这个jamiepinkham.com/post/9046964416/…,但实际上我很困惑为什么他会循环调用dispatch_group_wait,而不是最后一次?!

标签: ios asynchronous objective-c-blocks uidocument


【解决方案1】:

我发现将循环转换为递归是一种用于序列化异步操作的有用方法。 例如(这是一些记事本编程,可能无法编译,但你明白了):

此函数递归加载所有文档,然后调用完成处理程序:

- (void)loadDoc:(int)doc in:(NSArray*)localDocuments withCompletion:(void(^)(void))completion
{
    if (doc == [localDocuments count])
    {
        completion();
    }
    else
    {
        NSString* document = localDocuments[doc];

        if (![document hasSuffix:@".user"])
        {
            [self loadDoc:doc + 1 in:localDocuments withCompletion:completion];
        }
        else 
        {

            User* user=[[[User alloc] initWithFileURL:[NSURL fileURLWithPath:[[[AppDelegate localDocumentsDirectoryURL] path]
                                                                           stringByAppendingPathComponent:document]]] autorelease];
            [user openWithCompletionHandler:^(BOOL success)
            {
                [self.userList addObject:user];
                [self loadDoc:doc + 1 in:localDocuments withCompletion:completion];
            }];
        }
    }
}

为方便起见:

-(void)reloadUsersWithCompletion:(void(^)(void))completion
{

    NSArray* localDocuments = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[AppDelegate localDocumentsDirectoryURL] path] error:nil];
    [self loadDoc:0 in:localDocuments withCompletion:completion];
}

你展示你的对话:

{   // app finished loading

    [MyClass reloadUsersWithCompletion:^(void) {

        [LoginDialog show];    // this shall happen AFTER reloadUsers has loaded ALL documents
    }];
}

当然还有其他涉及线程和同步机制的方法,但我认为它们并不那么简单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多