как использовать sendAsynchronousRequest: queue: завершениеHandler: - PullRequest
74 голосов
/ 14 февраля 2012

Вопрос из двух частей

Часть первая: Я пытаюсь создать ASynchronous запрос к моей базе данных. В настоящее время я делаю это синхронно, однако я хочу изучить оба способа, чтобы лучше понять, что происходит.

В настоящее время я настроил свой синхронный вызов следующим образом.

- (IBAction)setRequestString:(NSString *)string
{
    //Set database address
    NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:@"http://127.0.0.1:8778/instacodeData/"]; // imac development

    //PHP file name is being set from the parent view
    [databaseURL appendString:string];

    //call ASIHTTP delegates (Used to connect to database)
    NSURL *url = [NSURL URLWithString:databaseURL];

    //SynchronousRequest to grab the data
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSError *error;
    NSURLResponse *response;

    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    if (!result) {
        //Display error message here
        NSLog(@"Error");
    } else {

        //TODO: set up stuff that needs to work on the data here.
        NSString* newStr = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
        NSLog(@"%@", newStr);
    }
}

Я думаю, что мне нужно сделать, это заменить вызов

NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

с AS-синхронной версией

sendAsynchronousRequest:queue:completionHandler:

однако я не уверен, что передать в очередь или завершение. Handler ... Любые примеры / решения будут с благодарностью.

Часть вторая: Я читал о многозадачности, и я хотел бы поддержать его, убедившись, что мои запросы на подключение выполнены, если есть прерывание. Я следовал этому примеру

В нем объясняется, как выиграть больше времени, если происходит прерывание, я понимаю, что он делает .. но не как применить его к этой связи? если у вас есть примеры / учебники, которые помогут мне понять, как их применять, это было бы здорово!

Ответы [ 6 ]

114 голосов
/ 14 февраля 2012

ЧАСТЬ 1:

NSURL *url = [NSURL URLWithString:urlString];

NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
    if ([data length] > 0 && error == nil)
        [delegate receivedData:data];
    else if ([data length] == 0 && error == nil)
        [delegate emptyReply];
    else if (error != nil && error.code == ERROR_CODE_TIMEOUT)
        [delegate timedOut];
    else if (error != nil)
        [delegate downloadError:error];
}];
38 голосов
/ 02 мая 2012

Вот пример:

NSString *urlAsString = @"http://www.cnn.com";
NSURL *url = [NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];


[NSURLConnection
         sendAsynchronousRequest:urlRequest
         queue:[[NSOperationQueue alloc] init]
         completionHandler:^(NSURLResponse *response,
                             NSData *data,
                             NSError *error) 
        {

         if ([data length] >0 && error == nil)
         {

                        // DO YOUR WORK HERE

         }
         else if ([data length] == 0 && error == nil)
         {
             NSLog(@"Nothing was downloaded.");
         }
         else if (error != nil){
             NSLog(@"Error = %@", error);
         }

     }];
26 голосов
/ 26 июня 2013

Для параметра очереди попробуйте следующее волшебство:

[NSOperationQueue mainQueue]

Это прекрасно работает, если вы обновляете пользовательский интерфейс по завершении запроса, поскольку основная очередь является основным потоком.По сути, это дает вам предыдущее поведение NSURLConnection.Однако, если вы планируете записывать в файл или распаковывать, вы можете выполнить его в фоновой очереди и затем отправить асинхронную обратно в основную очередь для обновлений пользовательского интерфейса.

9 голосов
/ 28 мая 2013

Я работал над аналогичной проблемой, я опубликовал этот вопрос и получил четкий ответ здесь , я надеюсь, что это поможет с частью 2.

Для части 1 то, что упоминали другиездесь хорошо, но вам нужно добавить еще одну проверку (я изменил ответ ниже).Вполне возможно, что ваш запрос вернет, скажем, ошибку 404 (страница не найдена), в этом случае вы не получите сообщение об ошибке, и данные будут> 0. Хороший ответ - 200, вы также можете проверить StatusCode для 404 или что-то еще.

     [NSURLConnection
     sendAsynchronousRequest:urlRequest
     queue:[[NSOperationQueue alloc] init]
     completionHandler:^(NSURLResponse *response,
                         NSData *data,
                         NSError *error) 
    {
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
     if ([data length] >0 && error == nil && [httpResponse statusCode] == 200)
     {

                    // DO YOUR WORK HERE

     }
4 голосов
/ 20 апреля 2016

Поскольку sendAsynchronousRequest:urlRequest queue:queue completionHandler: устарела в iOS 9, и вместо этого будет предложено использовать NSURLSession -dataTaskWithRequest:completionHandler:.Доступно с iOS 7 и более поздних версий .

Оригинал:

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 [NSURLConnection sendAsynchronousRequest:request
                                    queue:[NSOperationQueue mainQueue]
                        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
     // ...
 }];

По NSURLSession:

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 NSURLSession *session = [NSURLSession sharedSession];
 NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                         completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         // ...
     }];

 [task resume];
2 голосов
/ 18 октября 2016

sendAsynchronousRequest устарела в Swift.Перейдите к dataTaskWithRequest, к счастью, он используется почти так же.

if let url = NSURL(string:"http://your_url") {

    let request:NSURLRequest = NSURLRequest(URL: url)
    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config)

    let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in

    });

    task.resume()
}
...