iPhone NSURLConnection: connectionDidFinishLoading - как вернуть строку в вызывающий метод - PullRequest
4 голосов
/ 12 февраля 2010

Я рассмотрел похожие вопросы и ответы на стекопотоки, но я все еще в тупике.

Я новичок, и я действительно борюсь с этим. С iPhone я могу загрузить XML с URL-адреса, но не могу сохранить строку результата в переменной NSString и увидеть ее из вызывающей функции.

У меня есть следующие объявления в пользовательском классе:

@interface comms : NSObject {
    NSString *currURL, *receivedString;
    NSMutableData *receivedData;
    NSURLConnection *conn;
}

@property (copy, readwrite) NSString *currURL;
@property (copy, readonly) NSString *receivedString;
@property (nonatomic, assign) NSMutableData *receivedData;
@property (nonatomic, assign) NSURLConnection *conn;

-(void) getContentURL;

У меня есть следующий метод в классе связи:

-(void) getContentURL
{
    NSLog( @"Begin getContentURL." );

    // Request data related.
    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] 
                                    autorelease];
    [request setURL:[NSURL URLWithString: currURL]];

    // Content-Type related.
    [request setValue:@"application/x-www-form-urlencoded" 
   forHTTPHeaderField:@"Content-Type"];

    // Create Connection.
    conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    if (conn) {
        // The connection was established.
        receivedData = [[NSMutableData data] retain];
        NSLog( @"Data will be received from URL: %@", request.URL );
    }
    else
    {
        // The download could not be made.
        NSLog( @"Data could not be received from: %@", request.URL );
    }

    // PROBLEM - receivedString is NULL here.
    NSLog( @"From getContentURL: %@", receivedString );
}

Я создал необходимые делегаты в классе comms согласно следующему:

-(void)connection:(NSURLConnection *)connection didReceiveResponse:
    (NSURLResponse *)response
{
    // Discard all previously received data.
    [receivedData setLength:0];
}

-(void)connection:(NSURLConnection *)connection didReceiveData:
(NSData *)data
{
    // Append the new data to the receivedData.
[receivedData appendData:data];     
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // Connection succeeded in downloading the request.
    NSLog( @"Succeeded! Received %d bytes of data", [receivedData length] );

    // Convert received data into string.
    receivedString = [[NSString alloc] initWithData:receivedData 
        encoding:NSASCIIStringEncoding];
    NSLog( @"From connectionDidFinishLoading: %@", receivedString );

    // release the connection, and the data object
    [conn release];
    [receivedData release];
}

Я могу успешно вывести полученную строку с помощью NSLog в делегате connectionDidFinishLoading.

    // Convert received data into string.
    receivedString = [[NSString alloc] initWithData:receivedData 
        encoding:NSASCIIStringEncoding];
    NSLog( @"From connectionDidFinishLoading: %@", receivedString );

Однако, когда я вывожу строку receiveString в getContentURL, она становится нулевой (и, следовательно, также равна нулю в классе ViewController.m, из которого я вызываю класс comms).

    // PROBLEM - receivedString is NULL here.
    NSLog( @"From getContentURL: %@", receivedString );

Любые идеи о том, как я могу увидеть значение receiveString в getContentURL и из класса ViewController.m?

Ответы [ 2 ]

4 голосов
/ 12 февраля 2010

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

Если вы хотите сделать это синхронно, у вас будет два варианта:

  1. Используйте встроенный метод синхронной загрузки. Обратите внимание, что при блокировке пользователь не сможет взаимодействовать с пользовательским интерфейсом.
  2. Используйте функции C CFRunLoopRun () и CFRunLoopStop (), чтобы запустить цикл выполнения внутри вызывающей функции, дождаться завершения или сбоя загрузки, а затем вернуть управление обратно в вызывающий метод с помощью CFRunLoopStop ().
0 голосов
/ 03 августа 2012

Чтобы вернуть данные из метода делегатов, используйте кодовый блок.

См. Документация по блокам Apple .

...