7

我想知道如何正确执行以下操作:我有一个返回NSData对象的方法。它NSData从 a 中获取对象UIDocument。该NSData对象可能会变大,因此我想确保它在响应开始之前已完全加载。因此,我想从块本身返回方法的值。所以是这样的:

- (NSData*)getMyData {
  MyUIDocument *doc = [[MyUIDocument alloc] initWithFileURL:fileURL];
  [doc openWithCompletionHandler:^(BOOL success) {

    if (success) {
      return doc.myResponseData; // this is to be the return for the method not the block
    }
  }];
}

这会导致错误,因为return显然是指block's return

我怎样才能做到这一点而不必使线程阻塞等待/while循环?

谢谢。

4

3 回答 3

12

你不能。接受这样一个事实,即您尝试做的是异步的,并向您的getMyData方法添加一个完成块参数,该参数在调用内部完成处理程序时被调用。(并return从方法签名中删除):

- (void)getMyDataWithCompletion:(void(^)(NSData *data))completion {
    MyUIDocument *doc = [[MyUIDocument alloc] initWithFileURL:fileURL];
    [doc openWithCompletionHandler:^(BOOL success) {
        completion((success ? doc.myResponseData : nil));
    }];
}

swift中存在同样的问题,你可以添加一个类似的完成块:

func getMyData(completion: ((data: NSData?) -> Void) {
    data = ...
    completion(data)
}
于 2014-03-08T10:06:46.580 回答
0

open 方法是异步的,这就是为什么您必须提供一个在 open 完成时运行的块。您需要复制它并使您的方法也收到一个代码块,您将在打开完成时执行该代码块。

您还应该传递要包装的调用的成功参数或创建错误,您需要这样做,以便调用代码可以采取正确的行动。

- (void)getMyDataWithCompletion:(void(^)(NSData *data, BOOL success))completion
{
  MyUIDocument *doc = [[MyUIDocument alloc] initWithFileURL:fileURL];
  [doc openWithCompletionHandler:^(BOOL success) {
    completion(doc.myResponseData, success);
  }];
}
于 2014-03-08T10:25:07.483 回答
0

以下是如何使用 completionHandler 声明方法的方法:

Objective-C

- (void)getMyDataWithCompletionHandler:(void(^)(NSString *str))completionHandler
{
    completionHandler(@"Test");
}

斯威夫特-3

func showDatePicker(superc: UIViewController, completionHandler:@escaping (String) -> Void)  {
            completionHandler("Test")
}
于 2017-07-18T12:20:27.457 回答