国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS 邊下邊播的實現代碼

2020-07-26 02:37:40
字體:
來源:轉載
供稿:網友

項目中之前使用的是AVPlayer直接播放URL地址,但是不知道是相機的wifi不夠穩定還是代碼的問題,app總是出現緩沖卡頓,就考慮改寫成邊下邊播的模式,查過了許多資料,發現大部分都是用的同一種方法

AVAssetResourceLoaderDelegate 代理方法,來看看如何實現

首先要實現兩個必須的代理方法

AVAssetResourceLoaderDelegateObjective-C#pragma mark - AVAssetResourceLoaderDelegate//開始加載- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {  [self addLoadingRequest:loadingRequest];  return YES;}//取消加載- (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest {  [self removeLoadingRequest:loadingRequest];}#pragma mark - AVAssetResourceLoaderDelegate//開始加載- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {  [self addLoadingRequest:loadingRequest];  return YES;}//取消加載- (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest {  [self removeLoadingRequest:loadingRequest];}

然后要定義一個下載類,其實就是分段下載數據的下載器

AVAssetResourceLoaderDelegateObjective-C- (void)start {  NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[self.requestURL originalSchemeURL] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:RequestTimeout];  if (self.requestOffset > 0) {    [request addValue:[NSString stringWithFormat:@"bytes=%ld-%ld", self.requestOffset, self.fileLength - 1] forHTTPHeaderField:@"Range"];  }  self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];  self.task = [self.session dataTaskWithRequest:request];  [self.task resume];}#pragma mark - NSURLSessionDataDelegate//服務器響應- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {  if (self.cancel) return;  SRQLog(@"response: %@",response);  completionHandler(NSURLSessionResponseAllow);  NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response;  NSString * contentRange = [[httpResponse allHeaderFields] objectForKey:@"Content-Range"];  NSString * fileLength = [[contentRange componentsSeparatedByString:@"/"] lastObject];  self.fileLength = fileLength.integerValue > 0 ? fileLength.integerValue : response.expectedContentLength;  if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidReceiveResponse)]) {    [self.delegate requestTaskDidReceiveResponse];  }}//服務器返回數據 可能會調用多次- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {  if (self.cancel) return;  //SRQLog(@"收到響應了: %@",data);  self.cacheLength += data.length;  if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidUpdateCache)]) {    [self.delegate requestTaskDidUpdateCache];  }}//請求完成會調用該方法,請求失敗則error有值- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {  if (self.cancel) {    SRQLog(@"下載取消");  }else {    if (error) {      if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidFailWithError:)]) {        [self.delegate requestTaskDidFailWithError:error];      }    }else {      //可以緩存則保存文件      if (self.cache) {        [FileHandle cacheTempFileWithFileName:[NSString fileNameWithURL:self.requestURL]];      }      if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidFinishLoadingWithCache:)]) {        [self.delegate requestTaskDidFinishLoadingWithCache:self.cache];      }    }  }}- (void)start {  NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[self.requestURL originalSchemeURL] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:RequestTimeout];  if (self.requestOffset > 0) {    [request addValue:[NSString stringWithFormat:@"bytes=%ld-%ld", self.requestOffset, self.fileLength - 1] forHTTPHeaderField:@"Range"];  }  self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];  self.task = [self.session dataTaskWithRequest:request];  [self.task resume];}#pragma mark - NSURLSessionDataDelegate//服務器響應- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {  if (self.cancel) return;  SRQLog(@"response: %@",response);  completionHandler(NSURLSessionResponseAllow);  NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response;  NSString * contentRange = [[httpResponse allHeaderFields] objectForKey:@"Content-Range"];  NSString * fileLength = [[contentRange componentsSeparatedByString:@"/"] lastObject];  self.fileLength = fileLength.integerValue > 0 ? fileLength.integerValue : response.expectedContentLength;  if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidReceiveResponse)]) {    [self.delegate requestTaskDidReceiveResponse];  }}//服務器返回數據 可能會調用多次- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {  if (self.cancel) return;  //SRQLog(@"收到響應了: %@",data);  self.cacheLength += data.length;  if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidUpdateCache)]) {    [self.delegate requestTaskDidUpdateCache];  }}//請求完成會調用該方法,請求失敗則error有值- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {  if (self.cancel) {    SRQLog(@"下載取消");  }else {    if (error) {      if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidFailWithError:)]) {        [self.delegate requestTaskDidFailWithError:error];      }    }else {      //可以緩存則保存文件      if (self.cache) {        [FileHandle cacheTempFileWithFileName:[NSString fileNameWithURL:self.requestURL]];      }      if (self.delegate && [self.delegate respondsToSelector:@selector(requestTaskDidFinishLoadingWithCache:)]) {        [self.delegate requestTaskDidFinishLoadingWithCache:self.cache];      }    }  }}

最后將拿到的數據塞進AVAssetResourceLoaderDelegate代理中,交還給AVPlayer,就可以播放了

AVAssetResourceLoaderDelegateObjective-C- (BOOL)finishLoadingWithLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest {  //填充信息  CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)(MimeType), NULL);  loadingRequest.contentInformationRequest.contentType = CFBridgingRelease(contentType);  loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;  loadingRequest.contentInformationRequest.contentLength = self.requestTask.fileLength;  //讀文件,填充數據  NSUInteger cacheLength = self.requestTask.cacheLength;  NSUInteger requestedOffset = loadingRequest.dataRequest.requestedOffset;  if (loadingRequest.dataRequest.currentOffset != 0) {    requestedOffset = loadingRequest.dataRequest.currentOffset;  }  NSUInteger canReadLength = cacheLength - (requestedOffset - self.requestTask.requestOffset);  NSUInteger respondLength = MIN(canReadLength, loadingRequest.dataRequest.requestedLength);  //SRQLog(@"好不容易填充一次");  [loadingRequest.dataRequest respondWithData:[FileHandle readTempFileDataWithOffset:requestedOffset - self.requestTask.requestOffset length:respondLength]];  //如果完全響應了所需要的數據,則完成  NSUInteger nowendOffset = requestedOffset + canReadLength;  NSUInteger reqEndOffset = loadingRequest.dataRequest.requestedOffset + loadingRequest.dataRequest.requestedLength;  if (nowendOffset >= reqEndOffset) {    [loadingRequest finishLoading];    return YES;  }  return NO;}- (void)player{    self.resouerLoader     = [[ResourceLoader alloc] init];    self.asset = [AVURLAsset URLAssetWithURL:[self.videoUrl customSchemeURL] options:nil];    [self.asset.resourceLoader setDelegate:self.resouerLoader queue:dispatch_get_main_queue()];    _playerItem = [AVPlayerItem playerItemWithAsset:self.asset];    _players = [AVPlayer playerWithPlayerItem:_playerItem];}- (BOOL)finishLoadingWithLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest {  //填充信息  CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)(MimeType), NULL);  loadingRequest.contentInformationRequest.contentType = CFBridgingRelease(contentType);  loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;  loadingRequest.contentInformationRequest.contentLength = self.requestTask.fileLength;  //讀文件,填充數據  NSUInteger cacheLength = self.requestTask.cacheLength;  NSUInteger requestedOffset = loadingRequest.dataRequest.requestedOffset;  if (loadingRequest.dataRequest.currentOffset != 0) {    requestedOffset = loadingRequest.dataRequest.currentOffset;  }  NSUInteger canReadLength = cacheLength - (requestedOffset - self.requestTask.requestOffset);  NSUInteger respondLength = MIN(canReadLength, loadingRequest.dataRequest.requestedLength);  //SRQLog(@"好不容易填充一次");  [loadingRequest.dataRequest respondWithData:[FileHandle readTempFileDataWithOffset:requestedOffset - self.requestTask.requestOffset length:respondLength]];  //如果完全響應了所需要的數據,則完成  NSUInteger nowendOffset = requestedOffset + canReadLength;  NSUInteger reqEndOffset = loadingRequest.dataRequest.requestedOffset + loadingRequest.dataRequest.requestedLength;  if (nowendOffset >= reqEndOffset) {    [loadingRequest finishLoading];    return YES;  }  return NO;}- (void)player{    self.resouerLoader     = [[ResourceLoader alloc] init];    self.asset = [AVURLAsset URLAssetWithURL:[self.videoUrl customSchemeURL] options:nil];    [self.asset.resourceLoader setDelegate:self.resouerLoader queue:dispatch_get_main_queue()];    _playerItem = [AVPlayerItem playerItemWithAsset:self.asset];    _players = [AVPlayer playerWithPlayerItem:_playerItem];}

注意:此方法服務器端最好支持Range頭,這樣才是分段下載。

總結

以上所述是小編給大家介紹的iOS 邊下邊播的實現代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 察雅县| 福鼎市| 宁陕县| 天峻县| 泰宁县| 建湖县| 灵川县| 织金县| 崇阳县| 伽师县| 县级市| 腾冲县| 临清市| 高陵县| 南宁市| 全椒县| 尉氏县| 城固县| 西乌| 万全县| 乐业县| 边坝县| 合川市| 施甸县| 资溪县| 阳西县| 宁都县| 客服| 西青区| 宾川县| 娄底市| 大余县| 大荔县| 贵溪市| 儋州市| 墨脱县| 横山县| 绵竹市| 鹤庆县| 洛川县| 灵山县|