Ios 未调用NSURLConnection委托方法
我正在尝试使用NSURLConnection从web服务器下载一组文件,但在连接完成时,连接的委托方法从未被激发,因此文件从未被下载。我已经阅读了许多关于SO和其他来源的答案,并尝试了建议的修复方法,但没有效果,这让我觉得我在这里犯了一个不同的错误 我有一个viewController(InitViewController.m),它加载另一个类的方法: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
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,但我在复制粘贴时建议这样做。委托方法现在肯定会启动。