Ios 未调用NSURLConnection委托方法

Ios 未调用NSURLConnection委托方法,ios,objective-c,cocoa-touch,nsurlconnection,Ios,Objective C,Cocoa Touch,Nsurlconnection,我正在尝试使用NSURLConnection从web服务器下载一组文件,但在连接完成时,连接的委托方法从未被激发,因此文件从未被下载。我已经阅读了许多关于SO和其他来源的答案,并尝试了建议的修复方法,但没有效果,这让我觉得我在这里犯了一个不同的错误 我有一个viewController(InitViewController.m),它加载另一个类的方法: GetData *getDataInstance = [[GetData alloc] init]; [getDataInstance star

我正在尝试使用NSURLConnection从web服务器下载一组文件,但在连接完成时,连接的委托方法从未被激发,因此文件从未被下载。我已经阅读了许多关于SO和其他来源的答案,并尝试了建议的修复方法,但没有效果,这让我觉得我在这里犯了一个不同的错误

我有一个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];

}
我最初确实在一次更新中在一个单独的线程中启动了getDataInstance startUpdate,以使应用程序的“获取数据”部分与应用程序的“UI构建”部分分离,并认为这可能是问题所在,但现在我已经删除了该部分,甚至将其放入“[Connection scheduleInRunLoop:[nsrunlop mainRunLoop]forMode:NSDefaultRunLoopMode]"根据对这类问题的其他回答,等等

我肯定我会错过一些非常明显的东西,有什么想法吗

谢谢

编辑

我现在再次尝试了这段代码,但是在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被激发,但它的委托方法仍然没有被激发?

如果在其他线程中创建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);
}

}

只需更改这一行,其余代码保持原样。同时保留ScheduleUnloop行

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

当我想在并发NSO操作中启动NSURLConnection时,我也遇到了这个问题。 在主线程上执行连接帮助我解决了这个问题

- (void)start {

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(start)
                               withObject:nil
                            waitUntilDone:NO];
        return;
    }
}
此外,在[nsrunlop currentRunLoop]中安排SON连接也帮助我解决了这个问题:

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

您可以看看它是如何在CSUtils框架的一部分CSMessage类中完成的。您可以自行使用给定的代码:

将委托放入您的类中。例如:

@interface InitViewController : UIViewController<NSURLConnectionDelegate,NSURLConnectionDataDelegate>
@interface InitViewController:UIViewController

最后,我重新编写了整个课程,并让代表们被解雇

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)并将其保存在设备上。

您使用的是ARC吗?如果是,请确保诸如GetData之类的对象没有定义为弱对象,并在运行循环结束时解除分配。我将该行作为一个潜在的修复(有人建议在其他地方)将其删除不会有帮助。请确保不会过早解除分配。您可以通过实现-(void)dealloc并在那里放置一个NSLog或一个断点来实现这一点;看起来您需要将这些单独的类实例设置为实例变量,而不是局部变量。您对
NSURLConnection
使用了错误的初始值设定项
initWithRequest:delegate:
立即在调用线程上启动连接。相反,您应该使用
initWithRequest:delegate:startImmediately:
方法并传递
NO
以立即启动该部分。然后您可以在另一个线程运行循环中安排连接。此外,还应遵循@Volker的建议。奇怪的是,在上面的代码中,委托方法确实启动了,但它们似乎挂起了?就像它被困在一个无限循环或什么?RAM保持稳定,但应用程序不会返回其调用方法??这段代码对我来说非常适合。你能提供更多关于无限循环问题的信息吗?我不认为这是一个无限循环,只是看起来像。连接完成加载应用程序后,Xocde似乎已完成运行,并且应用程序现在正在自己运行,但应用程序尚未加载其UI或任何内容。您在哪里实现加载UI的代码?它是否在回调中?最初,initViewController构建了导航控制器,然后打开一个新线程,在该线程中构建了一个数据库(如果尚未构建)([CreateDBInstance createTables];),然后通过另一个类([GetDataInstance startUpdate];)进行填充。虽然这些都是在一个单独的线程上完成的,但UI是在另一个类mainViewController中构建的。我们刚刚尝试过这个,但仍然无法工作。我想我可能有一个更大的问题,如问题的评论所述。如果您不将其作为参数传递,它如何调用您的代理?您似乎正在使用同步API,而委托方式是用于异步任务。我相信委托已设置为self,但我在复制粘贴时建议这样做。委托方法现在肯定会启动。