killmice 2014-06-12
NSURLConnection:
NSURLConnection的基本使用可以参考:http://icolorbox.blog.163.com/blog/static/1960101312012850498446/
下载文件并显示进度
NSURL *url = [NSURL URLWithString: @"http://119.147.106.249/gdown_group11/M00/3F/15/d5Nq-UxBq88AAAAAAUn8QBO4rlY4306605/01_01_Android%E5%B9%B3%E5%8F%B0%E4%B8%80%E6%97%A5%E6%B8%B8.mp4?k=-4hoIXm9CXQ_Zo79EQprcQ&t=1346820047&u=3662410469-66934941-bei9apjt&s=307200&file=01_01_Android%E5%B9%B3%E5%8F%B0%E4%B8%80%E6%97%A5%E6%B8%B8.mp4"]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval: 100.0];//设置缓存和超时 NSURLConnection *connection = nil; connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; //初始化connection对象并马上执行,有的初始化方法并不是马上开始执行,而需要调用start方法。
二、实现connection的回调方法: - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {//该方法在响应connection时调用 NSLog(@"response"); self.data = [[NSMutableData alloc] init]; NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if(httpResponse && [httpResponse respondsToSelector:@selector(allHeaderFields)]){ NSDictionary *httpResponseHeaderFields = [httpResponse allHeaderFields]; mFileSize = [[httpResponseHeaderFields objectForKey:@"Content-Length"] longLongValue]; }//获取文件文件的大小 } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {//出错时调用 NSLog(@"error"); } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {//接受数据,在接受完成之前,该方法重复调用 NSLog(@"receive"); [_data appendData: data]; _displayLabel.text = [NSString stringWithFormat:(@"%6.1fkb/%6.1fkb"),[_data length]/1024.0,mFileSize/1024.0]; [_progressView setProgress: [_data length]/(float)mFileSize]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection {//完成时调用 NSLog(@"Finish"); NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"android.mp4"]; [_data writeToFile:filePath atomically:NO];//将数据写入Documents目录。 NSLog(@"%@",filePath); }
github上关于Restful风格访问客户端的示例,自己学习和理解:
ios关于自己访问URL获取返回的方式为UIURLConnection,我们再次基础上,封装Request,使其包含Header的设置,封装Response获取响应等等。
github地址:https://github.com/samvermette/SVHTTPRequest
NSURLConnection :
可以有两个办法让NSURLConnection在子线程中运行,即将NSURLConnection加入到run loop或者NSOperationQueue中去运行。
可以将NSTimer手动加入NSRunLoop,Cocoa库也为其它一些类提供了可以手动加入NSRunLoop的方法,这些类有NSPort、NSStream、NSURLConnection、NSNetServices,方法都是[scheduleInRunLoop:forMode:]形式。我暂时只介绍下最常用的NSURLConnection类,看看如何把NSURLConnection的网络下载加入到其它线程的run loop去运行。
如果NSURLConnection是在主线程中启动的,实际上它就在主线程中运行 -- 并非启动的另外的线程,但又具备异步运行的特性,这个确实是run loop的巧妙所在。如果对run loop有了初步的了解和概念后,实际上就能明白NSURLConnection的运行,实际也是需要当前线程具备run loop。
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; //将加入指定的run loop中运行,必须保证这时NSURLConnection不能启动,否则不起作用了
- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; //将取消在指定run loop中的运行,实际上就会停止NSURLConnection的运行
NSRunLoop *runloop; //global [self performSelectorInBackground:@selector(thread) withObject:nil]; //启动包含run loop的线程 NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; //注意这时不能先启动NSURLConnection [conn scheduleInRunLoop:runloop forMode:NSRunLoopCommonModes]; //指定在上面启动的线程中运行NSURLConnection [conn start]; //启动NSURLConnection - (void)thread { runloop = [NSRunLoop currentRunLoop]; //设置为当前线程的run loop值 while (condition) { [runloop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; //启动run loop } }
将NSURLConnection加入到NSOperationQueue中去运行的方式基本类似:
NSOperationQueue *queue = [[NSOperationQueuealloc] init]; NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; [conn setDelegateQueue:queue]; [conn start];
github上的例子封装一次NSURLConnection连接访问为 一个NSOperation,封装为一次Request,为一个操作线程。在NSOperation内部通过NSURLConnection访问网络,发起异步下载等内容。