我有一个轻击手势来提交数据:
- (void)tapSubmitDataRecognizer:(UISwipeGestureRecognizer *)sender {
if (_userNameOrEmailTextField.text != NULL) {
// NSURLSession
NSString *dataURL = [NSString stringWithFormat: @"http://localhost:8080/api/users/%@", _userNameOrEmailTextField.text];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:dataURL]];
[request setHTTPMethod:@"GET"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data != nil) {
// Convert the returned data into a dictionary.
NSError *error;
NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error != nil) {
NSLog(@"%@", [error localizedDescription]);
} else {
// If no error occurs, check the HTTP status code.
NSInteger HTTPStatusCode = [(NSHTTPURLResponse *)response statusCode];
// If it's other than 200, then show it on the console.
if (HTTPStatusCode != 200) {
NSLog(@"HTTP status code = %ld", (long)HTTPStatusCode);
}
passwordStoredInDatabase = [returnedDict valueForKey:@"password"];
if ([passwordStoredInDatabase isEqualToString:[self createSHA512:self.passwordTextField.text]]) {
NSLog(@"Passwords Match!");
UIViewController *demoIntro = [[DemoIntroViewController alloc] init];
demoIntro = [self.storyboard instantiateViewControllerWithIdentifier:@"DemoIntroViewController"];
[self.navigationController showViewController:demoIntro sender:self];
} else {
NSLog(@"Passwords Not Match!");
}
}
}
}] resume];
/**UIViewController *demoIntro = [[DemoIntroViewController alloc] init];
demoIntro = [self.storyboard instantiateViewControllerWithIdentifier:@"DemoIntroViewController"];
[self.navigationController showViewController:demoIntro sender:self];*/
}
}
除了导航部分,如果该部分放在完成处理程序中,一切都很有效。
请注意:
1)密码匹配。
2)导航部分在完成处理程序之外运行良好。
我需要将导航部分放在里面,因为我需要访问NSString" passwordStoredInDatabase"。
但是,如果从外部询问完成处理程序," passwordStoredInDatabase"一片空白。
如果您可以帮助我解决其中一个问题:
1)如何使导航部件在完成处理程序内工作?
2)如何访问NSString" passwordStoredInDatabase"从外部,它是在完成处理程序内生成的?它目前在外面为null,但在内部不为null。该变量在"实现"中声明。在一开始就阻止如下。
@implementation LoginViewController {
UITextField *activeTextField;
NSString *passwordStoredInDatabase;
}
打印一些调试消息后,可访问性问题似乎是执行的顺序。在NSURLSession部分完成后,如何确保NSURLSession部分之外的代码执行?我试过了
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
completionHandler(data);
}];
包装NSURLSession部分。但它仍然没有用。
答案 0 :(得分:2)
即使解决了UI更新的问题,我也不赞成您的代码设计 - 这会导致更大的问题。尝试利用面向对象编程(OOP)技术。
1)抽象。保持您的网络层和视图彼此不可知。我建议调查MVVM设计模式。避免在一个视图控制器中执行所有操作。但是这是一个例子,如果你想进行网络呼叫,并在收到响应后导航。
2)可能有多种方法,例如NSNotifications,委托模式等。这是一个非常基本的完成模块,可以帮助您进行最佳设计 -
-(void)initializeLoginFlow:(void (^)(BOOL loginStatus, NSError *error))completionHandler {
__block NSError *error;
__block BOOL success;
// Make a network request using NSURLSession
// Parse the response and update success object.
// Make sure to add weakSelf and use strongSelf inside the block.
if (completionHandler) {
completionHandler(success, error);
}
}
- (void)tapSubmitDataRecognizer:(UISwipeGestureRecognizer *)sender {
[self initializeLoginFlow:^(BOOL loginState, NSError *error) {
if (loginState) {
dispatch_async(dispatch_get_main_queue(), ^{
// Navigation. Passwords matched.
});
}
}];
}