简体   繁体   English

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

[英]IOS/Objective-C: Get call back from asynchronous method

At one point in my app, I call a method in a superclass to authenticate with the server.在我的应用程序中,我调用了超类中的一个方法来向服务器进行身份验证。 At the end of this method, I would like to run some code specific to the class that calls it.在这个方法的最后,我想运行一些特定于调用它的类的代码。 Is this the best way to wait for the response from the superclass before calling the additional code?这是在调用附加代码之前等待超类响应的最佳方式吗?

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

If so, what would the method look like?如果是这样,该方法会是什么样子? Something like the following?像下面这样的?

-(BOOL)authenticateWithServer (
//if fail {
return NO;
}
else {
return YES;
}
}

BOOL return types don't mix with async operations. BOOL 返回类型不与异步操作混合。 Instead you'll want to pass the result of authenticating with the server into the completion block and have your caller inspect it.相反,您需要将与服务器进行身份验证的结果传递到完成块中,并让您的调用者检查它。 I would highly recommend having a look at http://goshdarnblocksyntax.com for the correct block syntax.我强烈建议查看http://goshdarnblocksyntax.com以获得正确的块语法。

I'm pretty sure this is close to what you're attempting to do (added a fake delay in here to simulate the server request):我很确定这与您尝试执行的操作很接近(在此处添加了一个假延迟来模拟服务器请求):

@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

Here's an example if it in action:这是一个例子,如果它在行动:

假异步回调

Edit: because the completion blocks are nullable in the example I gave, you'll want to check whether one was passed in first.编辑:因为在我给出的例子中完成块是可以为空的,你需要检查是否首先传入了一个。

ie IE

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM