【问题标题】:Return data from NSOperation?从 NSOperation 返回数据?
【发布时间】:2013-10-15 05:25:33
【问题描述】:

我正在创建大量的NSOperations(子类)来对一堆数据进行排序。完成后,我希望他们“返回”该数据并将其放入可变数组或其他东西中。顺序无关紧要。

这样的事情可能吗?

【问题讨论】:

    标签: ios objective-c nsoperation


    【解决方案1】:

    协议委托模式的替代方案是完成块。例如,在一些基于NSURLConnection 的随机操作中,我定义了一个完成块typedef(只是为了简化后面的块语法),如果成功则返回NSData,否则返回NSError

    typedef void(^CustomOperationCompletionBlock)(NSData *data, NSError *error);
    

    然后我可以为我的NSOperation 子类定义一个块属性,例如:

    @property (nonatomic, copy) CustomOperationCompletionBlock successFailureBlock;
    

    我经常会复制我的init 操作方法,它可以让我在init 过程中设置完成块(除了我想要初始化的任何其他内容):

    - (instancetype)initWithURL:(NSURL *)url successFailureBlock:(CustomOperationCompletionBlock)successFailureBlock;
    

    然后,我在操作中处理错误和/或成功的各种方法将调用该完成块以将数据传回:

    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
        if (self.successFailureBlock) {
            // whether you call the completion block on the main queue, or use whatever queue the operation is using, is up to you. Here I'll call the completion block on the main queue:
    
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.successFailureBlock(nil, error);
            }];
        }
    
        [self completeOperation];
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        if (self.successFailureBlock) {
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.successFailureBlock(self.data, nil);
            }];
        }
    
        [self completeOperation];
    }
    

    并且,要将此操作与自定义完成块处理程序一起使用,当我启动我的操作时,我可以将自定义完成块传递给它。例如,如果成功则保存数据,否则记录错误:

    CustomOperation *operation = [[CustomOperation alloc] initWithURL:url successFailureBlock:^(NSData *data, NSError *error) {
        if (error)
            NSLog(@"CustomOperation error: %@", error);
        else         
            [data writeToFile:path atomically:YES];
    }];
    
    [queue addOperation:operation];
    

    显然,您将更改块 typedef 以传回对您的操作有意义的任何对象。但这说明了NSOperation 子类返回数据的基于块的机制的基本模式。

    【讨论】:

      【解决方案2】:

      当然。在 NSOperation 子类中声明一个委托。然后在操作完成后

      if([self.delegate respondsToSelector:@selector(YourDelegate:)]) {
          [(NSObject *)self.delegate performSelectorOnMainThread:@selector(YourDelegate:) withObject:self waitUntilDone:NO];
      }
      

      在用户界面中

      -(void)YourOperationDidFinish:(YourOperation *)downloader {
          if(downloader.downloadItem) {
              // processing with your object       
          }
      }
      

      【讨论】:

      • +1 显然,您应该在@selector 和委托中引用相同的方法名称。例如,如果委托中的方法是yourOperationDidFinish:,那么您将引用@selector(yourOperationDidFinish:)。更好的是,您可能应该为代表定义一个protocol,以消除此处的任何歧义。此外,在这个答案中隐含,声明delegate 属性weak 是谨慎的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-17
      相关资源
      最近更新 更多