ios - 如何在从主函数返回值之前等待委托(delegate)函数完成

标签 ios objective-c asynchronous camera delegates

我有一个自定义函数用于捕获真实深度相机信息,该函数在委托(delegate)函数完成处理捕获的照片之前返回。在我返回正确的值之前,我需要以某种方式等到委托(delegate)全部完成。

我尝试将主函数调用包装到一个同步块(synchronized block)中,但这并没有解决问题。

- (NSDictionary *)capture:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
{
  if (@available(iOS 11.1, *)) {
      // Set photosettings to capture depth data
      AVCapturePhotoSettings *photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecJPEG}];
      photoSettings.depthDataDeliveryEnabled = true;
      photoSettings.depthDataFiltered = false;
      @synchronized(self) {
          [self.photoOutput capturePhotoWithSettings:photoSettings delegate:self];
      }
  }
  // Somehow need to wait here until the delegate functions finish before returning
  return self.res;
}

被调用得太晚的委托(delegate)函数:

- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error
{
  Cam *camera = [[Cam alloc] init];
  self.res = [camera extractDepthInfo:photo];
}

目前 nil 在委托(delegate)被调用之前返回,只有在之后委托(delegate)函数才会将所需的结果分配给 self.res

最佳答案

我相信您正在寻找的是dispatch_semaphore_t

信号量允许您锁定线程,直到执行辅助操作。这样,您可以推迟方法的返回,直到委托(delegate)返回为止(如果您在辅助线程上操作)。

这种方法的问题是您将锁定线程!因此,如果您在主线程中操作,您的应用程序将变得无响应。

我建议您考虑将响应移至完成 block ,类似于:

-(void)capture:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject completion:(void (^)(NSDicitionary* ))completion {
    self.completion = completion
    ...
}

并在最后调用完成:

- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error
{
  Cam *camera = [[Cam alloc] init];
  self.res = [camera extractDepthInfo:photo];
  self.completion(self.res);
}

===编辑:Swift代码===

上面的代码将被翻译为:

var completion: (([AnyHashable: Any]) -> Void)?

func capture(options: [AnyHashable: Any], resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock, completion: @escaping ([AnyHashable: Any]) -> Void) {
    self.completion = completion
    ...
}

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    let cam = Cam()
    let result = cam.extractDepthInfo(photo)
    self.completion?(result)
}

这里需要注意的是,鉴于对象将被复制,因此需要在捕获方法中将完成标记为 @escaping

关于ios - 如何在从主函数返回值之前等待委托(delegate)函数完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57802760/

相关文章:

iphone - 将另一个 View 附加到同一 View "files owner"

ios - reloadItemsAtIndexPaths 上的 Collection View 崩溃

java - 将参数传递给 onProgressUpdate 时出现问题 - 异步方法

ios - 如何获取标注 c# xamarin 的 MKPlacemark 地址

iphone-sdk-3.0 - 在iOS应用程序中执行自定义位图绘制

ios - nativescript 编码错误

javascript - 如何递归且异步地构建未知大小的树?

java - 在 Java 中同步多个异步请求

ios - 在 Hapijs 后端处理 Alamofire 在 Swift 中发送的多部分/表单数据请求

objective-c - 有没有办法将自然语言日期 NSString 转换为 NSDate