Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSURLSession内部导航“;“完成处理程序”;不行_Ios_Objective C_Uinavigationcontroller_Nsurlsession_Completionhandler - Fatal编程技术网

Ios NSURLSession内部导航“;“完成处理程序”;不行

Ios NSURLSession内部导航“;“完成处理程序”;不行,ios,objective-c,uinavigationcontroller,nsurlsession,completionhandler,Ios,Objective C,Uinavigationcontroller,Nsurlsession,Completionhandler,我有一个点击手势来提交数据: - (void)tapSubmitDataRecognizer:(UISwipeGestureRecognizer *)sender { if (_userNameOrEmailTextField.text != NULL) { // NSURLSession NSString *dataURL = [NSString stringWithFormat: @"http://localhost:8080/api/users/%@", _userNa

我有一个点击手势来提交数据:

- (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”?当前外部为空,但内部不为空。变量在最开始的“实现”块中声明,如下所示

@implementation LoginViewController {
    UITextField *activeTextField;
    NSString *passwordStoredInDatabase;
}
在打印一些调试MSG之后,可访问性的问题似乎是执行顺序。如何确保NSURLSession部分之外的代码在NSURLSession部分完成后执行?我试过了

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
            completionHandler(data);
        }];

包装NSURLSession部分。但是它仍然不起作用。

即使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.
            });
        }
    }];
}

即使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.
            });
        }
    }];
}

始终在主队列上执行UI更新。@rmaddy你说得对。现在可以了!始终在主队列上执行UI更新。@rmaddy你说得对。现在可以了!