У меня есть NSURLConnection (два из них), и они работают в неправильном порядке.
Вот мой метод:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password {
NSURL *url = [NSURL URLWithString:@"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
NSString *postString = [NSString stringWithFormat:@"Pin=%@&Password=%@",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data 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
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Response was not JSON (from login), it was = %@", loggedInPage);
}
}
else {
NSLog(@"error: %@", error);
}
}];
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:@"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[request setHTTPMethod:@"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
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(@"Response was not JSON (from home), it was = %@", homePage);
}
}
else {
NSLog(@"error: %@", homeError);
}
}];
}
- (NSString *)percentEscapeString:(NSString *)string
{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)@" ",
(CFStringRef)@":/?@!$&'()*+,;=",
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}
Итак, два NSURLConnection
добавляются к [NSOperationQueue mainQueue]
. Мои результаты показывают, что второй NSURLConnection
выполняется раньше первого. Поэтому он пытается перейти на страницу, где я загружаю данные до того, как я вхожу в систему, поэтому (очевидно) возвращает ошибку «Вы не вошли в систему». Как мне запланировать их по очереди?
2 ответа
Проблема, как я подозреваю, вы уже поняли, заключается в том, что вы выполняете асинхронные сетевые запросы (что хорошо; вы не хотите блокировать основную очередь), поэтому нет уверенности в том, в каком порядке они завершатся.
Самый быстрый и простой ответ - просто поместить вызов второго запроса внутри блока завершения первого, а не после него. Вы не хотите делать вторую, если первая все равно не удалась.
Чтобы ваш код не стал громоздким, отделите логин от запроса на главную страницу. И вы можете использовать шаблон блока завершения, который является общим для асинхронных методов. Вы добавляете параметр в loginToMistarWithPin
, который указывает, что он должен делать после завершения запроса. У вас может быть один обработчик блока завершения для успеха и один для отказа:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password success:(void (^)(void))successHandler failure:(void (^)(void))failureHandler {
NSURL *url = [NSURL URLWithString:@"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
NSString *postString = [NSString stringWithFormat:@"Pin=%@&Password=%@",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(@"Response was = %@", responseJSON);
// assuming you validated that everything was successful, call the success block
if (successHandler)
successHandler();
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Response was not JSON (from login), it was = %@", loggedInPage);
if (failureHandler)
failureHandler();
}
}
else {
NSLog(@"error: %@", error);
if (failureHandler)
failureHandler();
}
}];
}
- (void)requestMainPage {
//Now redirect to assignments page
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
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(@"Response was not JSON (from home), it was = %@", homePage);
}
}
else {
NSLog(@"error: %@", homeError);
}
}];
}
Затем, когда вы захотите войти в систему, вы можете сделать что-то вроде:
[self loginToMistarWithPin:@"1234" password:@"pass" success:^{
[self requestMainPage];
} failure:^{
NSLog(@"login failed");
}];
Теперь измените эти параметры блока successHandler
и failureHandler
, чтобы они включали все данные, которые вам нужно передать, но, надеюсь, это иллюстрирует идею. Используйте короткие и сжатые методы и используйте параметры блока завершения, чтобы указать, что должен делать асинхронный метод, когда он будет выполнен.
Можете ли вы проверить ссылку ниже. Речь идет о том, чтобы заставить одну операцию ждать другой.
NSOperation - Принуждение операции к динамическому ожиданию других
Надеюсь это поможет.
Похожие вопросы
Связанные вопросы
Новые вопросы
ios
iOS - мобильная операционная система, работающая на Apple iPhone, iPod touch и iPad. Используйте этот тег [ios] для вопросов, связанных с программированием на платформе iOS. Используйте связанные теги [target-c] и [swift] для проблем, характерных для этих языков программирования.
https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage
изнутри блока? Я попытался просто напечататьhomeData
изsendAsynchronousRequest
, но это ничего мне не дало.POST
некоторые данные вPortalMainPage