我一直试图从里面一个块中获取一个值几个小时,我无法理解如何在完成时使用处理程序以及几乎所有内容。
这是我的代码:
+ (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]);
}];
}
所以我试图从returnString
方法NSLog downloadUserID
。
我第一次尝试返回,然后我意识到你不能从一个块内返回。所以现在我一直试图用:(void(^)(NSString *result))handler
来尝试从另一个类方法中访问它。
所以我从downloadUserID
方法调用getUserID
,并尝试记录returnString
字符串。它只是持续到零。它只打印From get userID
而没有别的。
如何访问returnString
方法块内的downloadUserID
?
答案 0 :(得分:2)
问题不在于block
本身,问题在于意识到该块是异步执行的。
在您的代码中,当您调用handler(returnString);
时,该块可能仍在另一个线程上执行,因此此时无法捕获该值。
你想要做的就是在阻挡区内移动该线(可能在结束时,在结束括号之前)。
答案 1 :(得分:0)
如果编写这样的包装器,则可以执行此操作。 在这种情况下,您需要一个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;
}
使用block调用委托人方法的方法。 并等待答案。 在这里我使用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];
});
}