Ios 从块内部返回方法对象

Ios 从块内部返回方法对象,ios,objective-c,block,uidocument,completionhandler,Ios,Objective C,Block,Uidocument,Completionhandler,我想知道如何正确地执行以下操作:我有一个方法可以返回NSData对象。它从UIDocument获取NSData对象。NSData对象可能会变大,因此我希望在响应开始之前确保它已完全加载。因此,我希望从块本身返回方法的值。比如说: - (NSData*)getMyData { MyUIDocument *doc = [[MyUIDocument alloc] initWithFileURL:fileURL]; [doc openWithCompletionHandler:^(BOOL su

我想知道如何正确地执行以下操作:我有一个方法可以返回
NSData
对象。它从
UIDocument
获取
NSData
对象。
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
    }
  }];
}
这会导致错误,因为
返回
显然是指
返回

如何在不进行线程阻塞等待/等待循环的情况下实现这一点


谢谢。

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

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

func getMyData(completion: ((data: NSData?) -> Void) {
    data = ...
    completion(data)
}

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

您还应该传递正在包装的调用的success参数或创建错误,您需要这样做,以便调用代码能够采取正确的操作

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

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

目标-C

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

func showDatePicker(superc: UIViewController, completionHandler:@escaping (String) -> Void)  {
            completionHandler("Test")
}

我很困惑。这不会再次从块内部返回方法值吗?不会,您将没有
return
语句。您将使用回调调用一个方法(passed success),该回调调用另一个回调(passed data)。正如Wain在回答中所说的,该调用是异步的,因此,与其调用一个方法并等待它返回并下一步处理结果,不如传递一段处理结果的代码,一旦加载文档,Wain的方法就会自动调用该块。在现实生活中的例子中,你说的不是“做这个,做完后告诉我,这样我就可以打电话给这个号码,告诉他这个和那个”,而是“做这个,做完后打这个号码,告诉他这个和那个”。
func showDatePicker(superc: UIViewController, completionHandler:@escaping (String) -> Void)  {
            completionHandler("Test")
}