2014-01-31 4 views
0

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

У меня есть ViewController (InitViewController.m), который загружает метод другого класса,:

GetData *getDataInstance = [[GetData alloc] init]; 
[getDataInstance startUpdate]; 

GetData.m затем делает некоторые проверки и работает класс, отвечающий за получение файлов:

GetFiles *getFilesInstance = [[GetFiles alloc] init]; 
[getFilesInstance doFilesNeedDownloading]; 

doFilesNeedDowngoading метод проверяет, нужен ли нам файл, а затем запускается getFiles:

-(void)getFile//:(NSString *) fullURL 
{ 

    // I have checked if the connection is run on the main thread and it is 
    NSLog(@"Is%@ main thread", ([NSThread isMainThread] ? @"" : @" NOT")); 

    NSURL *downloadURL = [NSURL URLWithString:fullURL]; 

    NSMutableURLRequest *dlRequest = [NSMutableURLRequest requestWithURL:downloadURL]; 
    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:dlRequest delegate:self]; 

    [theConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 

    [theConnection start]; 

    if(theConnection) { //me checking for connection which is 'true' 
     NSLog(@"Connection for %@ worked", fullURL); 
    } else { 
     NSLog(@"Connection for %@ failed", fullURL); 
    } 

} 
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 

    responseData = [[NSMutableData alloc] init]; 
    NSString *fileName = [[NSURL URLWithString:fullURL] lastPathComponent]; 
    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:fileName]; 
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 
    file = [NSFileHandle fileHandleForUpdatingAtPath:filePath]; 
    [file seekToEndOfFile]; 

} 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 

    [responseData appendData:data]; 
    [file seekToEndOfFile]; 
    [file writeData:data]; 

} 
-(void)connectionDidFinishLoading:(NSURLConnection *)connection { 

    [file closeFile]; 

} 

Первоначально я запускал startUpdate getDataInstance в отдельном потоке в обновлении, чтобы часть приложения «получать данные» отдельно от части «создания пользовательского интерфейса» в приложении и считала, что это может быть проблемой, но пока я удаляю что и даже вставить в '[theConnection scheduleInRunLoop: [NSRunLoop mainRunLoop] forMode: NSDefaultRunLoopMode]' в соответствии с другими ответами на этот вопрос на SO.

Я уверен, что будет что-то действительно очевидное, что я пропустил, любые идеи?

Спасибо,

EDIT

я сейчас попробовал этот код еще раз, но в initViewController, так что это в значительной степени первая вещь, которая вызывается, когда приложение нагрузки. Это уже не в другом классе или нить и т.п .:

-(void)getFile 
{ 
    fullURL = @"http://myURL.com/terms-and-conditions.txt"; 
    NSURL *downloadURL = [NSURL URLWithString:fullURL]; 
    NSMutableURLRequest *dlRequest = [NSMutableURLRequest requestWithURL:downloadURL]; 
    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:dlRequest delegate:self]; 

    [theConnection start]; 
} 
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 

    responseData = [[NSMutableData alloc] init]; 
    NSString *fileName = [[NSURL URLWithString:fullURL] lastPathComponent]; 
    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:fileName]; 
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 
    file = [NSFileHandle fileHandleForUpdatingAtPath:filePath]; 
    [file seekToEndOfFile]; 
} 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 

    [responseData appendData:data]; 
    [file seekToEndOfFile]; 
    [file writeData:data]; 
} 
-(void)connectionDidFinishLoading:(NSURLConnection *)connection { 

    [file closeFile]; 
} 

GetFile увольняют, но это делегат методы до сих пор не уволят?

+1

Вы используете ARC? Если да, убедитесь, что объекты, подобные вашему GetData, и такие не определены слабые и освобождаются в конце цикла выполнения. – Volker

+0

Я положил эту строку в качестве потенциального исправления (тот, который кто-то предложил в другом месте), удаление которого не помогает. – Ryan

+0

@ Volker - я использую ARC. GetData - это отдельный класс, импортированный в .h из initViewController – Ryan

ответ

0

В конце концов я переписал весь класс и получил делегат стрельбы.

NSString *currentURL = [NSString stringWithFormat:@"%@/api/sync", apiURL]; 
NSLog(@"URL = %@", currentURL); 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:currentURL]]; 
[request addValue:@"application/json" forHTTPHeaderField:(@"Accept")]; 
NSURLResponse *response = nil; 
NSError *error = nil; 
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

Вот делегаты, которые в настоящее время пожар:

- (void)connection:(FileURLConnection*)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    NSString *fileName = [[response URL] lastPathComponent]; 
    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:fileName]; 
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 
    connection.file = [NSFileHandle fileHandleForUpdatingAtPath:filePath]; 
} 
- (void)connection:(FileURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [connection.file writeData:data]; 
} 
- (NSCachedURLResponse *)connection:(FileURLConnection *)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse 
{ 
    return nil; 
} 
- (void)connectionDidFinishLoading:(FileURLConnection *)connection 
{ 
    [connection.file closeFile]; 
} 
- (void)connection:(FileURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    NSLog(@"GetFiles - didFailWithError - error : %@ for URL %@", error, connection.currentRequest.URL); 
} 

Класс Теперь скачивает файл (из моего собственного API) и сохраняет его на устройстве.

1

Если вы создаете NSURLConnection в другом потоке, вам нужно вручную запустить цикл выполнения.

Попробуйте с этим:

-(void)getFile 
{ 

NSURL *downloadURL = [NSURL URLWithString:fullURL]; 

NSMutableURLRequest *dlRequest = [NSMutableURLRequest requestWithURL:downloadURL]; 
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:dlRequest delegate:self]; 

[theConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 
[[NSRunLoop currentRunLoop] run]; 
[theConnection start]; 

if(theConnection) { //me checking for connection which is 'true' 
    NSLog(@"Connection for %@ worked", fullURL); 
} else { 
    NSLog(@"Connection for %@ failed", fullURL); 
} 

}

+0

Он упоминает, что он не работает даже в основном нить. – trojanfoe

+0

Странная вещь здесь в том, что с приведенным выше кодом методы делегата стреляют, но они, кажется, висеть? Как будто он застрял в бесконечном цикле или что-то в этом роде? RAM остается стабильной, но приложение не возвращается к его вызывающему методу? – Ryan

+0

Этот код отлично работает для меня. Можете ли вы дать больше информации о проблеме с бесконечным циклом? –

-1

Просто измените эту строку и отдых держать, как это в вашем коде. Сохраните также строку scheduleInRunLoop.

NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request 
                   delegate:self startImmediately:NO]; 
0

У меня тоже были проблемы, когда я хотел запустить NSURLConnection в параллельном NSOperation. Выполнение соединения по основной теме помогло мне решить проблему.

- (void)start { 

    if (![NSThread isMainThread]) { 
     [self performSelectorOnMainThread:@selector(start) 
           withObject:nil 
          waitUntilDone:NO]; 
     return; 
    } 
} 

Также планирование крестообразным в [NSRunLoop currentRunLoop] помог мне решить эту проблему:

self.connection = [[NSURLConnection alloc] initWithRequest:request 
                delegate:self 
              startImmediately:NO]; 
[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] 
          forMode:NSRunLoopCommonModes]; 
[self.connection start]; 

Вы можете посмотреть, как это делается в классе CSMessage, который является частью структуры CSUtils может.Вы можете использовать данный код по своему усмотрению: https://github.com/cloverstudio/CSUtils

+0

Просто попробовал это, и он все еще не работал. Я думаю, что у меня может быть большая проблема, как описано в комментариях к вопросу. – Ryan

0

Put делегат в вашем class.h как:

@interface InitViewController : UIViewController<NSURLConnectionDelegate,NSURLConnectionDataDelegate> 
Смежные вопросы