Как использовать sendAsynchronousRequest: queue: completeHandler:

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

Часть первая: Я пытаюсь создать 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];

с ASynchronous version

sendAsynchronousRequest:queue:completionHandler:

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

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

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

Ответ 1

PArt 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];
}];

Ответ 2

Вот пример:

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);
         }

     }];

Ответ 3

Для параметра очереди попробуйте эту магию:

[NSOperationQueue mainQueue]

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

Ответ 4

Я работаю над подобной проблемой, я разместил этот вопрос и получил четкий ответ здесь, я надеюсь, что это поможет с частью 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

     }

Ответ 5

Так как 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];

Ответ 6

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()
}