代码之家  ›  专栏  ›  技术社区  ›  user6631314

IOS/Objective-C:从异步方法获取回调

  •  -1
  • user6631314  · 技术社区  · 6 年前

         [super authenticateWithServer^(BOOL success, NSError *error) {
                 dispatch_async(dispatch_get_main_queue(), ^{
                 NSLog(@"heard back from method");
    if (success==YES) {
    //RUN MY CODE HERE
    }
                 });
                 }];
    

    如果是的话,这个方法是什么样的?像下面这样?

    -(BOOL)authenticateWithServer (
    //if fail {
    return NO;
    }
    else {
    return YES;
    }
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   R4N    6 年前

    BOOL返回类型不与异步操作混合。相反,您需要将服务器身份验证的结果传递到完成块中,并让调用者检查它。我强烈建议你看看 http://goshdarnblocksyntax.com 正确的块语法。

    我很确定这与您试图做的非常接近(在这里添加了一个假延迟来模拟服务器请求):

    @interface ViewController ()
    @property (strong, nullable) IBOutlet UILabel *resultLabel;
    - (void)authenticateWithServer:(void (^_Nullable)(BOOL success, NSError *_Nullable error))completion;
    - (void)_fakeUrlRequestToServerWithCompletion:(void(^_Nullable)(BOOL successFromServer, NSError *_Nullable errorFromServer))serverCompletion;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (IBAction)authWithServerButton:(id)sender {
        // call to authenticate with the results in the callback (not returning BOOL)
        [self authenticateWithServer:^(BOOL success, NSError * _Nullable error) {
            // callback will probably come in off the main queue so if you're doing some UI updates jump back on the main queue
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.resultLabel.text = [NSString stringWithFormat:@"Result = %@\nError = %@",success == 1 ? @"SUCCESS" : @"FAILURE", error == nil ? @"No Error" : error];
            }];
        }];
    }
    
    - (void)authenticateWithServer:(void (^_Nullable)(BOOL success, NSError *error))completion {
        // put this on the background queue so it doesn't hug
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            // call the fakeUrlRequestToServer method to simulate your async request
            [self _fakeUrlRequestToServerWithCompletion:^(BOOL successFromServer, NSError * _Nullable errorFromServer) {
                // completion block that was passed into the method, callback and pass along the success and error results
                completion(successFromServer, errorFromServer);
            }];
        });
    }
    
    - (void)_fakeUrlRequestToServerWithCompletion:(void(^_Nullable)(BOOL successFromServer, NSError *errorFromServer))serverCompletion {
        // fake sleep here for 2 seconds just to simulate waiting for the callback
        // never call sleep in your own code
        sleep(2);
        NSError *fakeError = nil;
        // just a fake auth success or failure
        BOOL fakeSuccess = arc4random() % 2 == 1 ? YES : NO;
        if (fakeSuccess == NO) {
            // fake error
            fakeError = [NSError errorWithDomain:@"FakeErrorDomain" code:22 userInfo:nil];
        }
        // completion block that was passed into the method, call back with the success and error params passed in
        serverCompletion(fakeSuccess, fakeError);
    }
    
    
    @end
    

    Fake Async Callback

    编辑: 因为在我给出的示例中,完成块是可以为null的,所以您需要检查是否首先传入了一个。

      if (completion) {
        completion(success, error);
      }