2013-09-16 3 views
0

Я разрабатываю приложение, которое связывается с сервером RESTful, чтобы получить некоторые данные, а затем с возвращенным ответом JSON для отображения этих данных.Проверьте блок GCD, так как процесс async занимает некоторое время

Использование вызовов UniRest и все работает хорошо. Главный вызов - «runUnirestRequest»

Узел вызова uni - это вызов для асинхронного GCD. Моя проблема заключается в том, что, поскольку я тестирую локально, вызов так быстро, что я не вижу индикатор активности. Он просто исчезает, прежде чем я смогу это увидеть.

Блок GCD возникает в режиме viewController viewDidLoad.

Что мне нужно для достижения: Попросите асинхронный unirest-вызов занять несколько секунд, чтобы имитировать ответ сервера медленным (не хотите, чтобы на самом деле останавливать приложение iOS на своих дорожках).

Прошу прощения за любые ошибки кодирования/вредные привычки, только делайте объективный c в течение недели, но я счастлив за любой дополнительный конструктивный крит. :)

Я попытался

sleep(5); // But bad idea as far as I can see. 

также попытался

[NSThread sleepForTimeInterval:5.0]; // but this doesn't seem to do anything. 

viewDidLoad

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [self createActivityIndicator]; 

    NSLog(@"viewDidLoad"); 
    NSLog(@"viewDidLoad->thread: %@", [NSThread currentThread]); 
    [messageLabel setText:@""]; 

    unirestQueue = dispatch_queue_create("com.simpleweb.pbs.dayDataUnirestRequest", NULL); 

    // Do any additional setup after loading the view from its nib. 
    daySalesFigures = [[PBSDaySales alloc] init]; 
    responseVal = [[HttpJsonResponse alloc] init]; 

    // Use Grand Central Dispatch to run async task to server 
    dispatch_async(unirestQueue, ^{ 
     [self runUnirestRequest:self.requestUrl]; 

    }); 

    dispatch_after(unirestQueue, dispatch_get_main_queue(), ^(void){ 
     [activityIndicator stopAnimating]; 
    }); 
} 

runUniRestRequest функции

- (void) runUnirestRequest:(NSString*)urlToGet 
{ 
    [NSThread sleepForTimeInterval:5.0]; 

    NSLog(@"runUnirestRequest called"); 

    HttpJsonResponse* response = [[Unirest get:^(SimpleRequest* request) { 
     [request setUrl:@"http://x.x.x.x:9000/Sales/Day/2013-02-14"]; 
    }] asString]; 

    NSString *jsonStr = [response body]; 

    SBJsonParser *jsonParser = [SBJsonParser new]; 

    id response2 = [jsonParser objectWithString:jsonStr]; 
    [self deserializeJsonPacket:(NSDictionary*)response2]; 

} 
+0

Просто примечание: Unirest - это всего лишь обертка вокруг «NSURLConnection», использующая исключительно _synchronous удобный_ метод 'sendSynchronousRequest: returnResponse: error:'. Это даже без уважительной ошибки. Хотя API довольно привлекателен, реализация - напротив - сомнительна. Надеюсь, что реализация будет улучшена. Итак, на данный момент вы немного ограничены субоптимальной реализацией: нет обработки ошибок, нет реального подхода к асинхронному общению, нет пользовательской проверки подлинности, нет больших тел данных ... и еще пара № – CouchDeveloper

ответ

3

dispatch_after Первый параметр - время. Вы проходите в unirestQueue, который dispatch_queue_t очередь согласно

unirestQueue = dispatch_queue_create("com.simpleweb.pbs.dayDataUnirestRequest", NULL); 

правильный код для dispatch_after, т.е. выполняя блок после некоторой задержки, как это:

double delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    // Do whatever you want 
}); 

Edit: О, я, наверное, увидеть, что вы пытаетесь выполнить :-) Вы думали, что dispatch_after означает «сделать что-то после этой очереди»? Нет, это «делать что-то через какое-то время»

Edit 2: Вы можете использовать код, как показано ниже, чтобы сделать что-то затраты времени в фоновом режиме и обновление пользовательского интерфейса, когда его сделали

// Start block on background queue so the main thread is not frozen 
// which prevents apps UI freeze 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    // Do something taking a long time in background 
    // Here we just freeze current (background) thread for 5s 
    [NSThread sleepForTimeInterval:5.0]; 

    // Everything in background thread is done 
    // Call another block on main thread to do UI stuff 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // Here you are in the main thread again 
     // You can do whatever you want 
     // This example just stops UIActivityIndicatorView 
     [activityIndicator stopAnimating]; 
    }); 
}); 

Редактировать 3: Я рекомендую this great article about GCD at raywenderlich.com для более подробная информация

+0

Ничего себе, это сработало отлично. Я не совсем понимаю потоки GCD в коде, который вы дали, поэтому придется сломать его и понять, как он работает, но спасибо. Один вопрос, который у меня был, был следующим: Выполняется вызов асинхронного Unirest в GCD бессмысленно?Разве это не то же самое, что запустить вызов unirest sync внутри блока GCD? Еще раз спасибо Лукасу, что тебе очень помогли. –

+0

Добро пожаловать. Я рад, что помог вам. Ну, я надеялся, что мой код достаточно прокомментирован :-) На ваш вопрос: я не знаю, как работает Unirest. Но в основном: если его синхронизированный запрос (блокировка - следующие строки кода дождитесь его завершения), вы должны запустить его в фоновом потоке (в блоке 'dispatch_async'). Если это async (выполняется сам по потоку bg и имеет обратный вызов успеха), нет необходимости называть его в другом потоке вообще, поскольку он будет работать в фоновом потоке вообще –

+0

Хорошо спасибо, Лукас высоко оценил. –

Смежные вопросы