我正在尝试使用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构建”部分分开,并认为这可能是问题但是现在我删除它,甚至根据SO上的这类问题的其他答案输入'[theConnection scheduleInRunLoop:[NSRunLoop 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被解雇但是它的委托方法仍然没有被解雇?
答案 0 :(得分: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);
}
}
答案 1 :(得分:0)
当我想在并发NSOperation中启动NSURLConnection时,我也遇到了这个问题。 在主线程上执行连接帮助我解决了这个问题。
- (void)start {
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(start)
withObject:nil
waitUntilDone:NO];
return;
}
}
在[NSRunLoop currentRunLoop]中安排sonnection也帮助我解决了这个问题:
self.connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:NO];
[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
[self.connection start];
您可以看看它是如何在CSMtilage框架中的CSMessage类中完成的。您可以自己使用给定的代码:https://github.com/cloverstudio/CSUtils
答案 2 :(得分:0)
将委托放在class.h中,如:
@interface InitViewController : UIViewController<NSURLConnectionDelegate,NSURLConnectionDataDelegate>
答案 3 :(得分: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)并将其保存在设备上。
答案 4 :(得分:-1)
只需更改此行并在代码中保持原样。保留scheduleInRunLoop行。
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self startImmediately:NO];