如何从块 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];
});
}
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];
});
}