简体   繁体   English

未调用NSURLConnection委托方法

[英]NSURLConnection delegate methods are not being called

I am trying to download a set of files from a web server using NSURLConnection but at the point the connection appears to be made, the connection's delegate methods never get fired and so the file never gets downloaded. 我正在尝试使用NSURLConnection从Web服务器下载一组文件,但此时似乎已建立连接,该连接的委托方法从未被触发,因此该文件从未被下载。 I have read many answers on SO and other sources and have tried the fixes that have been advised but to no avail, which makes me think I have made a different mistake here. 我已经阅读了关于SO和其他来源的许多答案,并尝试了已提出的修复,但均无济于事,这让我觉得我在这里犯了一个不同的错误。

I have a viewController (InitViewController.m) which loads another class's method: 我有一个viewController(InitViewController.m),它加载另一个类的方法:

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

GetData.m then does some checking and runs the class in charge of getting the files: 然后,GetData.m进行一些检查并运行负责获取文件的类:

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

doFilesNeedDowngoading method checks to see if we need the file and then runs getFiles: 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];

}

I did originally fire the getDataInstance startUpdate in a separate thread in an update to have the 'getting data' part of the app separate to the 'UI building' part of the app and thought this might be the issue but for now I have remove that and even put in'[theConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]' as per other answers to this kind of question on SO. 我最初确实在更新的单独线程中触发了getDataInstance startUpdate,以使应用程序的“获取数据”部分与应用程序的“ UI建筑物”部分分开,并认为这可能是问题所在,但现在我删除了甚至在SO上针对此类问题的其他答案,也放入“ [the connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]”。

I'm sure there will be something really obvious that I have missed, any ideas? 我敢肯定,我确实会漏掉一些东西,有什么主意吗?

Thanks, 谢谢,

EDIT 编辑

I have now tried this code again but in the initViewController so this is pretty much the first thing that is fired when the app loads. 我现在再次尝试了此代码,但是在initViewController中,所以这几乎是应用程序加载时触发的第一件事。 This is no longer in another class or thread etc.: 这不再在另一个类或线程等中:

-(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 gets fired but it's delegate methods still don't get fired? getFile被解雇了,但是它的委托方法仍然没有被解雇?

If you create NSURLConnection in other thread you have to manually start the run loop. 如果在其他线程中创建NSURLConnection,则必须手动启动运行循环。

Try with this: 试试这个:

-(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);
}

} }

I had this problems too when I wanted to start NSURLConnection in a concurrent NSOperation. 当我想在并发的NSOperation中启动NSURLConnection时,我也遇到了这个问题。 Performing connection on main thread helped me solve the problem. 在主线程上执行连接可以帮助我解决问题。

- (void)start {

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

Also scheduling sonnection in [NSRunLoop currentRunLoop] helped me to solve the problem: 另外,在[NSRunLoop currentRunLoop]中安排连接的时间有助于我解决问题:

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

You can take a look how it's done in CSMessage class that is part of CSUtils framework. 您可以在CSUtils框架的CSMessage类中了解它是如何完成的。 Feel free to use given code on your own: https://github.com/cloverstudio/CSUtils 随意使用给定的代码: https : //github.com/cloverstudio/CSUtils

将委托放在您的class.h中,例如:

@interface InitViewController : UIViewController<NSURLConnectionDelegate,NSURLConnectionDataDelegate>

In the end I re-wrote the whole class and got the delegates firing. 最后,我重新编写了全堂课,并让代表们解雇了。

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];

Here are the delegates that now fire: 以下是现在被解雇的代表:

- (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);
}

The class now downloads the file (from my own API) and saves it on the device. 该类现在下载文件(从我自己的API)并将其保存在设备上。

Just change this line and rest keep as it is in your code. 只需更改此行,并保持代码中的原样。 Keep the scheduleInRunLoop line also. 也保留scheduleInRunLoop行。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM