NSURLConnection и NSURLConnectionDataDelegate: обратные вызовы соединения не запускаются

Я хочу осуществить загрузку файлов с прогрессом с моего сервера. Я мой код я использую пользовательский класс, который делегируется

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://example.com"]];
            if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
                DownloadCallback *dc = [[DownloadCallback alloc] initWithCallbackProgress:^(long long res){
                    NSLog(@"%lld", res);
                } withCallbackReady:^(long long res){
                    NSLog(@"READY %lld", res);
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{

                    }];

                } withCallbackError:^(NSError * error) {
                    NSLog(@"READY %@", error.domain);
                }];

                NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:dc];
//                [connection setDelegateQueue:[[NSOperationQueue alloc] init]];
                [connection start];

заголовок:

@interface DownloadCallback: NSObject<NSURLConnectionDataDelegate>{
     @private void (^_progressHandler)(long long someParameter);
     @private void (^_readyHandler)(long long someParameter);
     @private void (^_errorHandler)(NSError *someParameter);
}
-(id) initWithCallbackProgress:(void(^)(long long))handler withCallbackReady:(void(^)(long long))handlerReady  withCallbackError:(void(^)(NSError*))handlerError;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
@end

тело:

@implementation DownloadCallback
-(id) initWithCallbackProgress:(void(^)(long long))handler withCallbackReady:(void(^)(long long))handlerReady  withCallbackError:(void(^)(NSError*))handlerError{
    self = [super init];
    if (self) {
        _progressHandler = [handler copy];
        _readyHandler = [handlerReady copy];
        _errorHandler = [handlerError copy];
    }
    return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
   // self.expectedTotalSize = response.expectedContentLength;

    // Call completion handler.
    if (_readyHandler != nil)
        _readyHandler(response.expectedContentLength);

    // Clean up.
//    [_completionHandler release];
    _readyHandler = nil;
    _progressHandler = nil;
    _errorHandler = nil;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//    self.recievedData += data.length;
    if (_progressHandler != nil)
        _progressHandler(data.length);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    if (_errorHandler != nil)
        _errorHandler(error);
}
@end

Но события обратного вызова не запускаются! Совсем!

Простой код синхронизации отлично работает:

    // Send a synchronous request
    NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                          returningResponse:&response
                                                      error:&error];
    if (error == nil) {
        // Parse data here
    }

Но мне нужен обратный звонок! Как это решить? Я не нашел решение в stackru. Кроме того, если я использую простой делегат в основной класс вместо DownloadCallback то же самое: обратные вызовы соединения тоже не запускаются.

1 ответ

Добавьте метод dealloc в ваш класс обратного вызова и выведите в нем точку останова или инструкцию log. Посмотрите, освобожден ли он до вызова обратного вызова.

Если это так, ваш экземпляр класса обратного вызова уничтожается слишком рано. Сделайте это свойством класса, который наверняка будет жить дольше, чем запрос.

Кроме того, вы должны убедиться, что этот код:

NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:dc];
[connection start];

вызывается в потоке переживает соединение и имеет цикл выполнения. Самый простой способ добиться этого - вызвать этот код в главной очереди. Ваш пример кода не показывает, в какой очереди он вызывается. Если это не работает, я предполагаю, что это потому, что вы вызываете его в фоновой очереди. Вы можете отправлять в фоновую очередь из делегатов обратных вызовов, которые вы хотите / должны.

В качестве идентификатора, если вы создаете что-то новое, вы должны попробовать использовать NSURLSession вместо NSURLConnection. NSURLSession более безопасен, прост в использовании и не устарел. NSURLConnection устарела.

Другие вопросы по тегам