як використовувати sendAsynchronousRequest: queue: completeHandler:


74

Питання з двох частин

Частина перша: Я намагаюся створити 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

sendAsynchronousRequest:queue:completionHandler:

однак я не впевнений, що передати в чергу або endHandler ... Будемо вдячні за будь-які приклади / рішення.

Частина друга: Я читав про багатозадачність, і я хотів би підтримати її, переконавшись, що мої запити на підключення завершені, якщо є переривання. Я наслідував цей приклад

У ній пояснюється, як отримати більше часу, якщо виникає переривання, я розумію, що це робить .. але не як застосувати його до цього з'єднання? якщо у вас є якісь приклади / підручники, які допоможуть мені зрозуміти, як це застосувати, це було б чудово!

Відповіді:


113

Частина 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];
}];

для викликів делегатів .. якого делегата я повинен включити до свого заголовного файлу?
C.Johns

Ви повинні делегувати його самому
mbh

2
Ці методи є у вашому класі. Ви можете перейменовувати ці методи як завгодно. Або не мати їх. але помістіть код у if, то інакше. або ви можете зателефонувати таким чином [самоотримані дані: дані];
mbh

12
Я вважаю NSURLErrorTimedOut, що прийняте значення закінчено ERROR_CODE_TIMEOUT.
Джо Масілотті,

2
Примітка: sendAsynchronousRequest:urlRequest queue:queue completionHandler:застаріло в iOS 9
Річард,

38

Ось зразок:

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

     }];

1
Ви не просочуєте об'єкт NSOperationQueue? Це схоже на це. Або ви використовуєте ARC і просто не згадали про це?
Лукас Петр

3
Я використовую ARC, просто не згадував про це. Дякую за питання!
Flea

Чи має рядок 'sendAsynchronousRequest: request' бути 'sendAsynchronousRequest: urlRequest'?
Мік,

@Flea Будь ласка, перегляньте моє відповідне запитання тут. stackoverflow.com/questions/24857919/…
Тайлер Пфафф,

25

Для параметра черги спробуйте наступне:

[NSOperationQueue mainQueue]

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


1
@MaciejSwic ні, оскільки в документації зазначено: "Черга: Черга операцій, до якої відправляється блок обробника, коли запит завершується або не вдається." Отже, це обробник завершення, який запускається в основному потоці, що може, а може і не добре, залежно від того, що ви хочете там зробити.
Алгоритм і блюз"

Ну, якщо ви оновлюєте інтерфейс, це те, що ви хочете. І немає сенсу додавати ускладнення запуску делегата у фоновому потоці, якщо це не потрібно. Використання головної черги дає таку ж поведінку, як і старий NSURLConnection, що в більшості випадків має бути нормальним.
malhal

9

Я працював над подібною проблемою, я відповідав на це питання і отримав чітку відповідь тут , я сподіваюся , що допомагає з ч.2.

У першій частині те, що добре згадані інші, але вам потрібно додати ще одну перевірку (я змінив відповідь нижче). Можливо, ваш запит поверне повідомлення про помилку 404 (сторінка не знайдена), і в цьому випадку ви не отримаєте, а помилка і дані будуть> 0. 200 - це хороша відповідь, ви також можете перевірити код стану на 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

Так sendAsynchronousRequest:urlRequest queue:queue completionHandler:були застаріла прошивка 9, і вона буде пропонувати використання NSURLSession«S-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

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()
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.