如何从块 iOS 中 return 方法对象

How to return method object from inside block iOS

Return 类型的方法是 NSArray,所以当我调用这个方法时,我得到 nil 或空数组。这是我的方法实现下面:

- (NSArray *)startParsing {
    __block NSArray *array;
    allProductsID = [[NSMutableArray alloc] init];
    NSString *string = [NSString stringWithFormat:@"http://%@:@%@",kPrestaShopAPIKey, kPrestaShopURLString];
    NSURL *url = [NSURL URLWithString:string];

    AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

    [manager GET:@"categories/21" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSXMLParser *parser = (NSXMLParser *)responseObject;
        [parser setShouldProcessNamespaces:YES];
        parser.delegate = self;
        [parser parse];
        //NSLog(@"First response %@", responseObject);
        for (int i = 0; i< [[self.xmlShop objectForKey:@"product"] count]; i++) {
            //NSLog(@"Second ID --> %@", [self.xmlShop objectForKey:@"product"][i]);
            NSString *productID = [NSString stringWithFormat:@"products/%@", [[self.xmlShop objectForKey:@"product"][i] objectForKey:@"id"]];
            [allProductsID addObject:productID];
        }
        array = [allProductsID copy];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error occured %@", [error localizedDescription]);
    }];
    return array;
}

谁能帮我解决这个问题?

你不能。
在您的情况下,该块是异步执行的。这意味着您的方法可能在块执行时已经返回。

您需要调用其他方法或从您的块中发送 NSNotification 以传递您的数组。

正如 Quentin 已经提到的,您不能直接这样做,因为您在内部执行异步请求。这意味着您的程序会启动请求,然后继续其下一条语句,而不是等待请求完成。你应该做的是

  • 使请求同步以使程序等待直到请求完成。但是请注意不要从主线程调用此方法,因为这会阻止您的应用程序继续响应,直到请求返回。
  • 使用块作为 startParsing 方法的回调(块用于实际请求回调的方式相同)

这会像下面这样:

- (void)startParsing:(void (^)(NSArray*))parsingFinished {
    allProductsID = [[NSMutableArray alloc] init];
    NSString *string = [NSString stringWithFormat:@"http://%@:@%@",kPrestaShopAPIKey, kPrestaShopURLString];
    NSURL *url = [NSURL URLWithString:string];

    AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

    [manager GET:@"categories/21" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        // do your parsing...
        parsingFinished([allProductsID copy]);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        parsingFinished([[NSArray alloc] init]); 
        // or return nil or provide a parsingFailed callback
    }];
}

你会这样称呼它

[yourObject startParsing:^(NSArray *parsedData) {
    // do something with the parsed data
}];

应该 return 枚举值的方法

- (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

中的委托方法
- (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];

    });
}