iOS 后台下载及管理库
说起下载第一个想起的就是ASI。一年前接手的新项目是核心功能是视频相关业务,在修改和解决视频下载相关的问题的时候让我体会到了ASI的下载的强大。后来新需求需要视频后台下载,使用NSURLSession的时候,更加深刻的体会到了ASI的强大好用。
后来替换下载的时候的原因:
- ASI开启后台下载功能,在iOS10的设备上,只能下载三分钟,然后就处于休眠状态
- AFN下载也是三分钟
- 测试后台下载的时候,不要用模拟器,使用用真机。模拟器APP处于后台时不会休眠。
NSURLSession的特点简介
通过NSURLSession创建的后台下载任务,保证了APP在后台或者退出的状态下,依然能进行下载任务,下载完成后通过唤醒APP,来将下载完成的数据保存到特定的位置。
- 在APP处于后台、锁屏状态下依然能后下载
- 最强大的是:APP在手动退出以及闪退后的状态下依然能够进行下载任务
NSURLSession
创建下载session
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];NSString *identifier = [NSString stringWithFormat:@"%@.BackgroundSession", bundleId];NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];session = [NSURLSession sessionWithConfiguration:sessionConfigdelegate:selfdelegateQueue:[NSOperationQueue mainQueue]];
- 在创建下载session的时候,需要一个下载标识,该标识需要在整个个系统内保证唯一,所以使用APP的bundle id。
- sessionConfig.allowsCellularAccess 控制是否可以通过蜂窝网络下载
当APP手动退出或者闪退后,重新启动时获取正在下载的tasks
NSMutableDictionary *dictM = [self.downloadSession valueForKey:@"tasks"]; [dictM enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {}];
AppDelegate后台下载回调
当APP处于后台下载状态时,需要处理下载完成后的数据的回调,这里就涉及了一个AppDelegate中的一个特别重要的回调
-(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler{NSLog(@"%s", __func__); }
该代理方法使用场景分析(详细分析过程见下面):
- 不实现该代理方法,手动进入App调用相关代理方法,部分情况下异常
- 实现该方法,不执行completionHandler,某一下载任务完成后唤醒App,继续其它下载任务,异常
- 实现该方法,执行completionHandler,某一下载任务完成后唤醒App,继续其它下载任务,一切正常
相关操作
创建下载任务:其实通过session创建的任务是NSURLSessionDownloadTask的子类__NSCFBackgroundDownloadTask,是苹果的私有API。
NSURL *downloadURL = [NSURL URLWithString:downloadURLString];NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];NSURLSessionDownloadTask *downloadTask = [self.downloadSession downloadTaskWithRequest:request];[downloadTask resume];
暂停下载:downloadTask有多种办法去暂停,但是我们选择有resume的下载方法,可以更加方便我们管理和多次暂停继续。
[downloadTask cancelByProducingResumeData:^(NSData * resumeData) { }];
继续下载:通过resumeData继续下载。
NSURLSessionDownloadTask *downloadTask = [self.downloadSession downloadTaskWithResumeData:data]; [downloadTask resume];
取消或者删除下载
[downloadTask cancel];
相关代理方法说明
下载任务开始后,下载文件的进度回调方法。
bytesWritten
某一断点续传过程中已经下载的数据大小,totalBytesWritten
已经下载的文件的大小;totalBytesExpectedToWrite
当前需要下载的文件的大小- (void)URLSession:(NSURLSession *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTaskdidWriteData:(int64_t)bytesWrittentotalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{}
下载任务继续开始下载时的回调方法
- (void)URLSession:(NSURLSession *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTaskdidResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {}
当资源发生重定向时回调的方法。NSURLSession内部自己处理定向回调
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)responsenewRequest:(NSURLRequest *)requestcompletionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler{}
讲个小故事:去年元旦左右,我们是使用ASI下载视频的,甘肃的一个用户反馈,视频死活不能下载。但是我们在公司网络,国外VPN,4G,家里的网络测试下载没有问题,并且进行n次的测试,没有复现该问题,后来只能只作罢。然后过年回家,腊月30到家的,和家人吃年夜饭过后,看春晚,实在没意思,突然想起这个问题,然后就测试代码,我去,还真的是个必现的bug,死活下载不了。卡断点,调试一会后,发现下载资源URL被302重定向了,然后我们项目中的以前集成ASI,并不支持重定向,最后在失败的回调用,判断了下,如果是重定向,拿到新的URL重新去下载,想想也是坑啊。 下载的资源经过cdn加速后,猜测cdn在不同的region做了不同的处理。然后北京没事,其它的地域有可能重定向了。当时改完代后有点小开心, 因为怕同事说我猿气太重,所以在公司提交的代码...
当下载任务完成后的代理回调方法,回调的参数
location
是下载完成后的文件,在沙盒当中存在的路径- (void)URLSession:(NSURLSession *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{}
假如在后台下载完成的回调,会触发该回调方法。
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{ }
下载失败后的回调。暂停,停止,失败都会触发。区别是:正常状态下的暂停会回调resumeData,如果resumeData不为空的话我们需要保存该数据,方便下次继续。
- (void)URLSession:(NSURLSession *)sessiontask:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ }
后台下载相关回调
AppDelegate 回调方法3种情况分析:
实现代理 执行completionHandler 现象 1 否 部分情况下异常 2 是 否 部分情况下异常 3 是 是 一切正常 1. 不实现代理方法
当不实现AppDelegate代理方法的时候,简单的下载是没有任何问题。NSURLSession下载完成后相关代理方法执行顺序如图:代理调用顺序只有手动将后台的App进入前台后会调用成功的回调,处理相关的数据。假如有3个下载任务则会回调3次
URLSession:downloadTask:didFinishDownloadingToURL:
方法。缺点和问题:
- 如果下载完成后,不进入前台或者手动杀死进程,则丢失下载数据
- 等待下载的任务无法继续下载
- 下载完成后,在后台无法使用本地通知
2. 实现代理方法,不执行completionHandler
AppDelegate 方法
-(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler
completionHandler 作用:首先看苹果SDK的解释:
// Applications using an NSURLSession with a background configuration may be launched or resumed in the background in order to handle the
// completion of tasks in that session, or to handle authentication. This method will be called with the identifier of the session needing
// attention. Once a session has been created from a configuration object with that identifier, the session's delegate will begin receiving
// callbacks. If such a session has already been created (if the app is being resumed, for instance), then the delegate will start receiving
// callbacks without any action by the application. You should call the completionHandler as soon as you're finished handling the callbacks.最后两句是说明completionHandler的,大概意思是:回调callbacks,只要session创建将会开始接收到。回调callbacks没有对你的应用程序进行任何的处理,一旦完成处理callbacks,你应该调用completionHandler。
英语不好感觉说的云里雾里的。callbacks应该是暂停继续任务时受到的代理方法。说的是我们完成下载任务后应该调用completionHandler
completionHandler作用测试代理:
#pragma mark - test code - (void)applicationWillResignActive:(UIApplication *)application{[self testTimer];NSLog(@"%s",__func__); }- (void)applicationDidBecomeActive:(UIApplication *)application {[self.timer invalidate];self.timer = nil;self.duration = 0;NSLog(@"%s", __func__); }- (void)testTimer {self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerRun) userInfo:nil repeats:true];[self.timer fire]; }- (void)timerRun {_duration += 1;NSLog(@"%zd", _duration); }
completionHandler具体作用:
这个回调的作用有点牛皮。通过上面代理可以测试出completionHandler,在第一个后台下载任务完成时回调,这时后台App已经被唤醒,定时器开始输出计时秒数。然后其它的下载任务完成时不会再次回调该方法。所有下载任务完成时,没有处理completionHandler计时器继续运行。 调用执行时completionHandler计时器停止运行,App继续处于休眠状态。虽然不知道completionHandler做了哪些处理,但是通过测试现象得出大概的作用。他用来控制后台的App被唤醒后继续处于休眠状态,节约系统资源。
所以不执行completionHandler App如果不重新启动,处于后台时会一直在运行状态。下载任务正常。
3. 实现代理方法,执行completionHandler
上面我们分析了completionHandler大概作用。所以所有后台任务下载完成后调用completionHandler,是App处于正常的状态。相关代理调用顺序:代理调用顺序completionHandler调用时机:
所有的下载任务下载完成后调用。感兴趣的可以看YCDowloadSession下载库对completionHandler的处理逻辑。YCDownloadSession
YCDownloadSession是我写的一个视频后台下载的库。里面拥有我对视频下载的详细的处理过程和管理的库。
该视频下载库主要有四个核心类:YCDownloadSession,YCDownloadTask,YCDownloadItem,YCDownloadManager
- YCDownloadSession:对NSURLSession的进一步分装,是一个单例,所有的下载任务都是由其生成和管理。是最主要的核心类。实现了下载的代理方法,通过一个可下载的url,生成一个YCDownloadTask,并且将该task的所有数据进行实时存储。
- YCDownloadTask 将YCDownloadSession里的代理方法进一步封装和扩展,保存session生成和所需要的一些下载信息和数据。
- YCDownloadItem 存放需要下载的视频的信息
- YCDownloadManager 管理下载视频操作,生成一个YCDownloadItem,并且实时保存相关信息(下载状态,文件大小,已下载文件大小,以及其它的需要和UI交互的数据),然后调用YCDownloadSession去下载该视频。
图解
YCDownloadSession结构图解YCDownloadSession和YCDownloadTask是两个核心类。与YCDownloadManager和YCDownloadItem相互独立。大家和可以通过YCDownloadSession和YCDownloadTask自定义需要的下载管理类的信息类。
使用效果图
- 单文件下载测试
单文件下载
- 多视频下载测试
多视频下载
- 通知
通知用法
AppDelegate设置后台下载成功回调方法
-(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler{[[YCDownloadSession downloadSession] addCompletionHandler:completionHandler]; }
如果想要多个任务在后台同时进行,必须要进行设置上述的代理方法。YCDownloadSession内部会处理该回调方法(completionHandler的作用将会在blog里详细说明),内部处理逻辑:
//等task delegate方法执行完成后去判断该逻辑//URLSessionDidFinishEventsForBackgroundURLSession 方法在后台执行一次,所以在此判断执行completedHandlerif (status == YCDownloadStatusFinished) {if ([self allTaskFinised]) {[[NSNotificationCenter defaultCenter] postNotificationName:kDownloadAllTaskFinishedNoti object:nil];//所有的任务执行结束之后调用completedHanlderif (self.completedHandler) {NSLog(@"completedHandler");self.completedHandler();self.completedHandler = nil;}}}
直接使用YCDownloadSession下载文件
self.downloadURL = @"http://dldir1.qq.com/qqfile/QQforMac/QQ_V6.0.1.dmg";- (void)start {[[YCDownloadSession downloadSession] startDownloadWithUrl:self.downloadURL delegate:self saveName:nil]; } - (void)resume {[[YCDownloadSession downloadSession] resumeDownloadWithUrl:self.downloadURL delegate:self saveName:nil]; }- (void)pause {[[YCDownloadSession downloadSession] pauseDownloadWithUrl:self.downloadURL]; }- (void)stop {[[YCDownloadSession downloadSession] stopDownloadWithUrl:self.downloadURL]; }//代理 - (void)downloadProgress:(YCDownloadTask *)task downloadedSize:(NSUInteger)downloadedSize fileSize:(NSUInteger)fileSize {self.progressLbl.text = [NSString stringWithFormat:@"%f",(float)downloadedSize / fileSize * 100]; }- (void)downloadStatusChanged:(YCDownloadStatus)status downloadTask:(YCDownloadTask *)task {if (status == YCDownloadStatusFinished) {self.progressLbl.text = @"download success!";}else if (status == YCDownloadStatusFailed){self.progressLbl.text = @"download failed!";} }
使用自定义的管理类(YCDownloadManager 视频类型文件专用下载管理类)下载。假如视频下载完成,自定义保存名称,那么使用fileId来标识。如果fileId为空使用下载URL的MD5的值来保存
/**开始/创建一个后台下载任务。downloadURLString作为整个下载任务的唯一标识。下载成功后用downloadURLString的MD5的值来保存文件后缀名取downloadURLString的后缀名,[downloadURLString pathExtension]*/ + (void)startDownloadWithUrl:(NSString *)downloadURLString fileName:(NSString *)fileName imageUrl:(NSString *)imagUrl;/**开始/创建一个后台下载任务。fileId作为整个下载任务的唯一标识。下载成功后用fileId来保存, 要确保fileId唯一文件后缀名取downloadURLString的后缀名,[downloadURLString pathExtension]*/ + (void)startDownloadWithUrl:(NSString *)downloadURLString fileName:(NSString *)fileName imageUrl:(NSString *)imagUrl fileId:(NSString *)fileId;
蜂窝煤是否允许下载的方法(YCDownloadSession, YCDownloadManager)
YCDownloadSession: /**是否允许蜂窝煤网络下载,以及网络状态变为蜂窝煤是否允许下载,必须把所有的downloadTask全部暂停,然后重新创建。否则,原先创建的下载task依旧在网络切换为蜂窝煤网络时会继续下载@param isAllow 是否允许蜂窝煤网络下载*/ - (void)allowsCellularAccess:(BOOL)isAllow;YCDownloadManager: /**获取当前是否允许蜂窝煤访问状态*/ - (BOOL)isAllowsCellularAccess;
设置最大同时进行下载的任务数
YCDownloadSession: /**设置下载任务的个数,最多支持3个下载任务同时进行。NSURLSession最多支持5个任务同时进行但是5个任务,在某些情况下,部分任务会出现等待的状态,所有设置最多支持3个*/ @property (nonatomic, assign) NSInteger maxTaskCount;YCDownloadManager: /**设置下载任务的个数,最多支持3个下载任务同时进行。*/ + (void)setMaxTaskCount:(NSInteger)count;
下载完成的通知
本地通知(YCDownloadManager实现):
/**本地通知的开关,默认是false,可以根据通知名称自定义通知类型*/ + (void)localPushOn:(BOOL)isOn;
当前session中所有的任务下载完成的通知。 不包括失败、暂停的任务:
kDownloadAllTaskFinishedNoti
某一的任务下载完成的通知object为YCDownloadItem对象:
kDownloadTaskFinishedNoti
某一任务下载的状态发生变化的通知:
kDownloadStatusChangedNoti
主要用于状态改变后,及时保存下载数据信息。GitHub连接
https://github.com/onezens/YCDownloadSession欢迎各位关注该库,如果你有任何问题请issues我,将会随时更新新功能和解决存在的问题。
遇到的一些问题
这里总结下载开发YCDownloadSession下载库中碰到的一些问题
苹果下载相关SDK关系图
下载资源重定向的问题
YCDownloadSession 内部标识一下下载task的时候,使用的下载资源的URL来标识。如果该资源被301/302重定向到一个另一个URL后,会存在两个URL。标识用的URL在代理回调的NSURLSessionTask或者NSURLSessionDownloadTask的currentRequest中取的url,这样就出现了一个问题,重定向后通过URL拿不到下载的task;originalRequest属性可以拿到重定向前的URL使用该属性解决这个问题。苹果下载相关SDK关系图可看它们之间关系。断点续传
NSURLSessionDownloadTask的断点续传是由其内部自己控制实现。在暂停某一下载任务的时候有两个方法:
cancel
内部自己控制断点续传数据,拿到对应task可以继续下载。如果拿不到,不可继续。cancelByProducingResumeData:^(NSData * resumeData) {}
通过session继续下载[downloadSession downloadTaskWithResumeData:data]
,需要自己保存处理resumeData,可以满足很多情况下的续传。部分下载资源不可断点续传
YCDownloadSession Demo中的测试用的下载资源来自百度视频,可以正常下载。网易视频的资源和部分响应头不完整的资源在暂停下载之后拿不到resumeData而回调失败的情况。
- 百度视频资源:
https://vd1.bdstatic.com/mda-hiqmm8s10vww26sx/mda-hiqmm8s10vww26sx.mp4\?playlist\=%5B%22hd%22%5D\&auth_key\=1506158514-0-0-6cde713ec6e6a15bd856fbb4f2564658\&bcevod_channel\=searchbox_feed
响应头:
通过Mac Terminal自带的curl命令获取响应头curl -I https://vd1.bdstatic.com/mda-hiqmm8s10vww26sx/mda-hiqmm8s10vww26sx.mp4\?playlist\=%5B%22hd%22%5D\&auth_key\=1506158514-0-0-6cde713ec6e6a15bd856fbb4f2564658\&bcevod_channel\=searchbox_feed
HTTP/1.1 200 OK Server: bfe/1.0.8.13-sslpool-patch Date: Tue, 10 Oct 2017 07:43:02 GMT Content-Type: video/mp4 Content-Length: 19727666 Connection: keep-alive ETag: "125b8b749037921ccd03120fb0f90189" Last-Modified: Fri, 15 Sep 2017 09:42:18 GMT Accept-Ranges: bytes Content-MD5: EluLdJA3khzNAxIPsPkBiQ== x-bce-debug-id: MTAuMTgxLjk5LjE0OlNhdCwgMTYgU2VwIDIwMTcgMTE6MzA6MzYgQ1NUOjE4MzY0NTgzMjM= x-bce-request-id: b3c7857b-b71a-4cd4-ab98-8676319dc8cb x-bce-storage-class: STANDARD Ohc-Response-Time: 1 0 0 0 0 94 Access-Control-Allow-Origin: * Cache-Control: max-age=2592000
- 网易视频资源:
http://flv2.bn.netease.com/videolib3/1706/07/gDNOH8458/HD/gDNOH8458-mobile.mp4
响应头:curl -I http://flv2.bn.netease.com/videolib3/1706/07/gDNOH8458/HD/gDNOH8458-mobile.mp4HTTP/1.1 200 OK Expires: Thu, 09 Nov 2017 07:00:42 GMT Date: Tue, 10 Oct 2017 07:00:42 GMT Server: nginx Content-Length: 43260722 Cache-Control: max-age=2592000 Content-Type: video/mp4 Via: 1.1 zhshx117:1 (Cdn Cache Server V2.0)[11 200 2], 1.1 xxz195:3 (Cdn Cache Server V2.0)[94 200 2], 1.1 PStjdgdx3jx152:4 (Cdn Cache Server V2.0)[154 200 2] Connection: keep-alive cache: state cdn-user-ip: 101.96.129.122 cdn-ip: 42.81.28.152 cdn-source: chinanetcenter
- 响应头异常视频资源:
https://www.zmzfile.com:9043/rt/route\?fileid\=152260954bdfa322725ba58df2ab1e2c2e3a6050
响应头:curl -I https://www.zmzfile.com:9043/rt/route\?fileid\=152260954bdfa322725ba58df2ab1e2c2e3a6050HTTP/1.1 302 Found Server: nginx/1.12.1 Date: Tue, 10 Oct 2017 07:53:23 GMT Content-Type: text/plain; charset=utf-8 Connection: keep-alive Location: http://175.6.228.3:9021?id=152260954bdfa322725ba58df2ab1e2c2e3a6050 Ts: 1716489继续取302资源的响应头 curl -I http://175.6.228.3:9021\?id\=152260954bdfa322725ba58df2ab1e2c2e3a6050 Ts: 1716489 curl: (52) Empty reply from serverXcode 输出NSURLSessionDownloadTask的response信息: <NSHTTPURLResponse: 0x13cee64d0> { URL: [http://60.211.203.204:9031?id=152260954bdfa322725ba58df2ab1e2c2e3a6050](http://60.211.203.204:9031/?id=152260954bdfa322725ba58df2ab1e2c2e3a6050) } {status code: 200,headers {Connection = Close;"Content-Length" = 247272762;Server = p4pcacher; } }
目前这个问题还正在探索解决的办法中。目前来看断点续传是系统内部实现的,苹果SDK没有提供一些相关的操作,如果出现类似的问题,那么只能和后台沟通,解决响应头相关的信息来解决这个问题。
作者:LeavesLife
链接:http://www.jianshu.com/p/2ccb34c460fd
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章:

(转) 使用Speech SDK 5.1文字转音频
下载地址: http://www.microsoft.com/en-us/download/details.aspx?id10121 SeppchSDK51.exe 语音合成引擎 SpeechSDK51LangPack.exe 支持日语和简体中文需要这个支持。 SpeechSDK51MSM.exe 如果要将引擎作为产品的一部分发布需要这个。 Sp5TTintXP.exe XP下Mike和…

IE8下面的line-height的bug
当line-height小于正常值时,超出的部分将被剪裁掉转载于:https://www.cnblogs.com/jsingleegg/p/js_ie8.html

Hadoop集群的基本操作(一:HDFS操作及MapReduce程序练习)
实验 目的 要求 目的: 理解HDFS在Hadoop体系结构中的角色;熟练使用HDFS操作常用的Shell命令;了解Hadoop集群MapReduce程序的简单使用;(上传WordCount的jar执行程序;使用WordCount进行MapReduce计算&#x…
iOS实现动态区域裁剪图片
阅读 249收藏 322017-11-29原文链接:github.com想自己动手搭建一个 Discuz 论坛?试试腾讯云上实验室吧https://cloud.tencent.com/developer/labs 裁剪图片功能在很多上传图片的场景里都需要用到,一方面应用服务器可能对图片的尺寸大小有限制…

每天CookBook之JavaScript-062
鼠标进入事件鼠标离开事件<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>062</title> </head> <body> <div><img src"001" alt"001"><img src…

spring + Quartz定时任务配置
<bean id"exportBatchFileTask" class"com.ydcn.pts.task.ExportBatchFileTask"></bean><bean id"readBatchFileTask" class"com.ydcn.pts.task.ReadBatchFileResultTask"></bean><!-- 生成开卡档…

Hadoop集群的基本操作(二:HBase的基本操作)
实验 目的 要求 目的: 1、HBase的基本应用 要求: 完成HBase的高可用完全分布模式的安装;HBase的相关服务进程能够正常的启动;HBase控制台能够正常使用;表创建、数据查询等数据库操作能够正常进行; …

Abaqus用户子程序umat的学习
Abaqus用户子程序umat的学习 说明:在文件中,!后面的内容为注释内容。本文为学习心得,很多注释是自己摸索得到。如有不正确的地方,敬请指正。 ! —————————————————————————— ! 1、为何需要…

PHP:isset()-检测变量是否被设置
isset()-检测变量是否被设置 bool isset(mixed $var [, mixed $...]),检查变量是否被设置,并且不是NULL。var,要检测的变量,...其他变量,允许有多个变量。 返回值:如果var存在并且不是NULL,则返回TRUE&…

Android通过ShareSDK实现新浪微博分享
ShareSDK社会化分享的官方说明:是中国最大的APP内分享服务提供商,ShareSDK社会化分享,全面支持微信,微博,QQ空间,来往,易信,Facebook等国内外40个平台。 ShareSDK官方网站ÿ…

Hadoop集群的基本操作(三:HBase的基本操作)
实验 目的 要求 目的: MySQL数据库的基本命令;MySQL数据库中使用SQL语句;MySQL数据库中数据库,表,数据的操作;要求: 完成MySQL的集群版的安装;MySQL集群的相关服务进程能够正常启…
iOS通过Plist保存离线调试日志
最近需要测试APP在iPhone没连接USB情况下定位时间间隔的情况,固把nslog的日志信息保存成本地Plist文件,以便测试结束后查阅运行时的日志。 一、新建一个保存日志的方法,参数为每次定位成功的时间(作为key),…

关于变量名前面加m的问题
为什么很多人写代码会在变量名前面加一个小写的m? 上大学那会儿就对这个问题感到很好奇。于是网上到处搜,有人说是member的意思。于是后来一直就这么认为。 最近在读Android源码,发现很多系统变量命名时都加了m,而有的变量又没有加…

谷歌推出情境感知API
在 Google I/O 2016 大会上,我们宣布推出新的 Google Awareness API,让您的应用可以利用快照和围栏智能应对用户情境,并且仅需占用极少量的系统资源。 所有开发者均可以通过 Google Play 服务获取 Google Awareness API。 利用 7 种不同类型的…

Hadoop集群的基本操作(四:Hive的基本操作)
实验 目的 要求 目的: (1)掌握数据仓库工具Hive的使用; 要求: 掌握数据仓库Hive的使用;能够正常操作数据库、表、数据; 实 验 环 境 五台独立PC式虚…

【转】通过Hibernate将数据 存入oracle数据库例子
一、 Hibernate介绍 Hibernate是基于对象/关系映射(ORM,Object/Relational Mapping)的一个解决方案。ORM方案的思想是将对象模型表示的对象映射到关系型数据库中,或者反之。Hibernate目前是ORM思想在Java中最成功、最强大的实现。…
自动布局按钮排列平均分布
需要实现如下图所示的主页面布局,需要两排按钮,每一排都自动平均分布,Android的话直接用LinearLayout水平布局,并设置layout_weight即可,对于iOS,网上有使用代码实现,感觉略麻烦,我直…

maven3 手动安装本地jar到仓库
安装命令: mvn install:install-file -Dfile{Path/to/your/ojdbc.jar} -DgroupIdcom.oracle -DartifactIdojdbc6 -Dversion11.2.0 -Dpackagingjar我自己安装oracle14.jar 时命令如下:mvn install:install-file -DgroupIdcom.oracle -DartifactIdojdbc14 …

Hadoop集群的基本操作(五:Sqoop的基本操作)
实验 目的 要求 目的: 掌握ETL工具Sqoop的使用;掌握MySQL和HDFS之间的数据转换;要求: 掌握ETL工具Sqoop的使用;能够正常操作数据库、表、数据; 实 验 环 境 五台…

NEWS - InstallShield 2013 SP1发布
2013的这个国庆假期期间,InstallShield厂商Flexerasoftware(中文名:福莱睿)发布了最新版本InstallShield 2013的SP1,由于这个升级包带来一些新的技术支持和变化,所以特地给大家介绍一下: 1. 支持…

iOS 高德导航按返回后报错 解决
最近项目要添加导航功能,用了高德导航SDK,很郁闷每次从地图界面返回前一页面都报错,弄了很久,最终从高德开发者论坛找到一解决方法,可以试一下。 在导航的ViewController的viewWillDisappear中调用如下方法࿰…

Oracle的基本操作(一:子查询与常用函数)
1、描述TO_CHAR和TO_DATE函数的用法。 TO_CHAR(d|n[,fmt]):把日期和数字转换为指定格式(fmt)的字符串; TO_DATE(x[,fmt]):把一个字符串一fmt格式转换为一个日期类型; 举例:select to_char(sysdate,yyyy-mm-dd) "char", to_date(…

易买网的一些增删改查
正如题目所说的一样,今天就来说说易买网中的一些增删改查,主要的功能有注册、用户管理以及商品分类等! 1.注册 1.1 注册涉及到了一个ajax远端技术,主要是用来控制注册用户在数据库中是否存在: <script>$(function(){//焦点移出表单时$("#user…
iOS后台持续定位并定时上传
最近做一个考勤APP,功能很简单,就是一直在后台运行,每隔固定时间向服务器上传一次位置信息。持续运行24小时测试,功能实现。 1.ViewController.h文件: #import <CoreLocation/CoreLocation.h>并实现CLLocationMa…

jQuery UI vs Kendo UI jQuery Mobile vs Kendo UI Mobile
jQuery UI vs Kendo UI http://jqueryuivskendoui.com/#introduction jQuery Mobile vs Kendo UI Mobile http://jqueryuivskendoui.com/#mobile-introduction Kendo UI教程 http://www.cnblogs.com/pangblog/archive/2013/09/10/3313135.html转载于:https://www.cnblogs.com/j…

Oracle的基本操作(二:存储过程)
1、编写一个存储过程,根据输入的工作类型,输入该工作的平均工资。 -- Created on 2018/9/30 by YANXUKUNcreate or replace procedure avgsal(v_job in scott.emp.job%type)isavgsal2 number;beginselect avg(sal) into avgsal2 from scott.emp where j…

web11 Struts处理表单数据
电影网站:www.aikan66.com 项目网站:www.aikan66.com 游戏网站:www.aikan66.com 图片网站:www.aikan66.com 书籍网站:www.aikan66.com 学习网站:www.aikan66.com Java网站:www.aikan66.co…

瀑布流开源这两天
想必第一眼看到 Masonery 效果的人们会和当初的我有同样的感觉,惊艳!尤其是在你双击浏览器标题栏的空白处之后,所有的区块都在默默寻找自己的位置,无论大小,就像上海虹桥火车站涌入地铁的人群。和技术实现无关…

iOS网络请求总结
*说明:文章中HTTP为宏定义的http地址,事例通过app_login.action的接口,通过传递policyNum、plateNum、phoneNum三个参数进行登录操作 一、方法1: Foundation框架 NSURLConnection (1)同步请求:同…

MongoDB数据库(一:基本操作)
1、创建名称为自己姓名拼音缩写的数据库; 2、创建名为姓名拼音缩写col的集合,如dugncol; 3、删除2中的集合,重新创建格式如dugncolnew的集合; 4、在3创建的集合中,插入10条文档数据,要求分别插入…