【问题标题】:Return value from inside block (Objective-C)从块内部返回值(Objective-C)
【发布时间】:2014-03-22 17:24:01
【问题描述】:

我已经尝试从 inside 块中获取值几个小时了,我无法理解如何在完成时使用处理程序以及几乎所有内容。
这是我的代码:

+ (void)downloadUserID:(void(^)(NSString *result))handler {
    //Now redirect to assignments page

    __block NSMutableString *returnString = [[NSMutableString alloc] init]; //'__block' so that it has a direct connection to both scopes, in the method AND in the block


    NSURL *homeURL = [NSURL URLWithString:@"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
    NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
    [requestHome setHTTPMethod:@"GET"]; // this looks like GET request, not POST

    [NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError) {
         // do whatever with the data...and errors
         if ([homeData length] > 0 && homeError == nil) {
             NSError *parseError;
             NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
             if (responseJSON) {
                 // the response was JSON and we successfully decoded it

                 //NSLog(@"Response was = %@", responseJSON);
             } else {
                 // the response was not JSON, so let's see what it was so we can diagnose the issue

                 returnString = (@"Response was not JSON (from home), it was = %@", [[NSMutableString alloc] initWithData:homeData encoding:NSUTF8StringEncoding]);
                 //NSLog(returnString);
             }
         }
         else {
             //NSLog(@"error: %@", homeError);
         }
    }];
    //NSLog(@"myResult: %@", [[NSString alloc] initWithData:myResult encoding:NSUTF8StringEncoding]);
    handler(returnString);
}

- (void)getUserID {
    [TClient downloadUserID:^(NSString *getIt){
        NSLog([NSString stringWithFormat:@"From get userID %@", getIt]);
    }];

}

所以我正在尝试从downloadUserID 方法对returnString 进行NSLog。 我首先尝试返回,然后我意识到你不能从块内返回。所以现在我一直在尝试使用:(void(^)(NSString *result))handler 来尝试从另一个类方法访问它。

所以我从getUserID 方法调用downloadUserID,并尝试记录returnString 字符串。它只是继续为零。它只打印From get userID 而没有其他内容。

如何访问downloadUserID 方法块内的returnString

【问题讨论】:

  • 一旦你有你想要返回的值,你需要从完成处理程序内部调用handler

标签: ios objective-c objective-c-blocks


【解决方案1】:

问题不在于block 本身,问题在于实现该块是异步执行的。

在您的代码中,当您调用 handler(returnString); 时,该块可能仍在另一个线程上执行,因此此时您无法捕获该值。

您可能想要做的是将该行移动到块内(可能在末尾,在右大括号之前)。

【讨论】:

  • 更准确地说,在调用 handler 时(在 OP 的代码中),异步请求甚至还没有发送,更不用说被处理了。
  • 谢谢,我将handler(returnString) 移动到块中,它返回了我希望的字符串。
【解决方案2】:

如果您编写这样的包装器,您可以这样做。 在这种情况下,您需要一个 while 循环来等待块的响应。

应该返回枚举值的方法

- (RXCM_TroubleTypes) logic_getEnumValueOfCurrentCacheProblem
{
    RXCM_TroubleTypes result = RXCM_HaveNotTrouble;
    NetworkStatus statusConnection = [self network_typeOfInternetConnection];

    RXCM_TypesOfInternetConnection convertedNetStatus = [RXCM convertNetworkStatusTo_TypeOfInternetConnection:statusConnection];


    BOOL isAllowed = [self someMethodWith:convertedNetStatus];
    if (isAllowed){
        return RXCM_HaveNotTrouble;
    }else { 
        return RXCM_Trouble_NotSuitableTypeOfInternetConnection;
    }

   return result;
}

使用块调用委托方法的方法。 并等待它的回答。 这里我使用while循环。只需检查块中每 0.5 秒的答案

- (BOOL) isUserPermissioned:(RXCM_TypesOfInternetConnection)newType
{
    __block BOOL isReceivedValueFromBlock = NO;
    __block BOOL result = NO;
    __block BOOL isCalledDelegateMethod = NO;

    dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    dispatch_sync(aQueue,^{

        while (!isReceivedValueFromBlock) {
            NSLog(@"While");
            if (!isCalledDelegateMethod){
                [self.delegate rxcm_isAllowToContinueDownloadingOnNewTypeOfInternetConnection:newType
                                                                                   completion:^(BOOL isContinueWorkOnNewTypeOfConnection) {
                                                                                       result = isContinueWorkOnNewTypeOfConnection;
                                                                                       isReceivedValueFromBlock = YES;
                                                                                   }];
                isCalledDelegateMethod = YES;
            }
            [NSThread sleepForTimeInterval:0.5];

        }
    });
    return result;
}

ViewController中的Delegate方法

- (void) rxcm_isAllowToContinueDownloadingOnNewTypeOfInternetConnection:(RXCM_TypesOfInternetConnection)newType
                                                             completion:(void(^)(BOOL isContinueWorkOnNewTypeOfConnection))completion
{
    __weak ViewController* weak = self;

    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Alert"
                                                                       message:@"to continue download on the new type of connection"
                                                                preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *ok = [UIAlertAction actionWithTitle:@"YES" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            completion(YES);
        }];

        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"NO" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            completion(NO);
        }];

        [alert addAction:cancel];
        [alert addAction:ok];
        [weak presentViewController:alert animated:YES completion:nil];

    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多