對於近期開發中用到的第三方類做了一些簡單的整理, 分享...
AFNetworking
AFNetworking 是一個輕量級的網絡請求API類庫, 是以NSURLConnection, NSOperation和其他方法爲基礎的.
目前比較推薦的iOS網絡請求組件, 默認網絡請求時異步的, 通過block回調的方式對返回的數據進行處理.
需要注意的時AFNetworking對服務器返回的輸數據類型ContentType要求比較嚴格, 默認支持application/json的返回. 所以可能需要添加對text/html返回的支持. 否則就無法獲得返回的數據.
AFNetworking是異步的, 也可以使用同步的網絡請求方法
常見問題:
1. AFNetworking作用都有哪些?
NSURLConnection提供了+sendAsynchronousRequest:queue:completionHandler:和+sendAsynchronousRequest:queue:completionHandler: ,但是AFNetworking提供了更好的功能
*AFURLConnectionOperation和它的子類繼承NSOperation的,允許請求被取消,暫停/恢復和由NSOperationQueue進行管理。
*AFURLConnectionOperation也可以讓你輕鬆得完成上傳和下載,處理驗證,監控上傳和下載進度,控制的緩存。
*AFHTTPRequestOperation和它得子類可以基於http狀態和內容列下來區分是否成功請求了
*AFNetworking可以將遠程媒體數據類型(NSData)轉化爲可用的格式,比如如JSON,XML,圖像和plist。
*AFHTTPClient提供了一個方便的網絡交互接口,包括默認頭,身份驗證,是否連接到網絡,批量處理操作,查詢字符串參數序列化,以及多種表單請求
*的UIImageView+ AFNetworking增加了一個方便的方法來異步加載圖像。
2. AFNetworking是否支持緩存?
可以,NSURLCache及其子類提供了很多高級接口用於處理緩存
如果你想將緩存存儲再磁盤,推薦使用SDURLCache
3.如何使用AFNetworking上傳一個文件?
NSData *imageData = UIImagePNGRepresentation(image);
NSURLRequest *request = [client multipartFormRequestWithMethod:@"POST" path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id formData) {
[formData appendPartWithFileData:imageData mimeType:@"image/png" name:@"avatar"];
}];
4.如何使用AFNetworking下載一個文件?
先創建一個AFURLConnectionOperation對象,然後再使用它的屬性outputStream進行處理
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:@"download.zip" append:NO];
5.如何解決:SystemConfiguration framework not found in project
請導入:
#import
#import
6.當應用程序退出時,如何保持持續的請求?
AFURLConnectionOperation有一個叫setShouldExecuteAsBackgroundTaskWithExpirationHandler:的方法用於處理在應用程序進入後臺後,進行持續的請求
[self setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
}];
一些實例:
1.XML 請求
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://api.flickr.com/services/rest/?method=flickr.groups.browse&api_key=b6300e17ad3c506e706cb0072175d047&cat_id=34427469792@N01&format=rest"]];
AFXMLRequestOperation *operation = [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {
XMLParser.delegate = self;
[XMLParser parse];
} failure:nil];
[operation start];
2.圖片請求:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];
[imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]];
3.圖片上傳處理,監測上傳狀態:
didiwei 17:28:57
NSURL *url = [NSURL URLWithString:@"http://api-base-url.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"avatar.jpg"], 0.5);
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id formData) {
[formData appendPartWithFileData:imageData name:@"avatar" fileName:@"avatar.jpg" mimeType:@"image/jpeg"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation start];
4.在線流媒體請求
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/encode"]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.inputStream = [NSInputStream inputStreamWithFileAtPath:[[NSBundle mainBundle] pathForResource:@"large-image" ofType:@"tiff"]];
operation.outputStream = [NSOutputStream outputStreamToMemory];
[operation start];
SDWebImage
SDWebImage作爲i圖片處理工具, 爲開發者提供了豐富完善的網絡圖片處理, 通常用於解決最佔內存的圖片緩存問題.
SDWebImage的常用方法
1. sd_setImageWithURL:
//圖片緩存的基本代碼,就是這麼簡單
[self.image1 sd_setImageWithURL:imagePath1];
2. sd_setImageWithURL: completed:
//用block 可以在圖片加載完成之後做些事情
[self.image2 sd_setImageWithURL:imagePath2 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"這裏可以在圖片加載完成之後做些事情");
}];
3. sd_setImageWithURL: placeholderImage:
1
2
//給一張默認圖片,先使用默認圖片,當圖片加載完成後再替換
[self.image1 sd_setImageWithURL:imagePath1 placeholderImage:[UIImage imageNamed:@"default"]];
4. sd_setImageWithURL: placeholderImage: completed:
//使用默認圖片,而且用block 在完成後做一些事情
[self.image1 sd_setImageWithURL:imagePath1 placeholderImage:[UIImage imageNamed:@"default"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"圖片加載完成後做的事情");
}];
5. sd_setImageWithURL: placeholderImage: options:
//options 選擇方式
[self.image1 sd_setImageWithURL:imagePath1 placeholderImage:[UIImage imageNamed:@"default"] options:SDWebImageRetryFailed];
- SDWebImage 內部實現原理
入口 setImageWithURL:placeholderImage:options: 會先把 placeholderImage 顯示,然後
SDWebImageManager 根據 URL 開始處理圖片. - 進入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交給 SDImageCache 從緩存查找圖片是否已經下載 queryDiskCacheForKey:delegate:userInfo:.
- 先從內存圖片緩存查找是否有圖片,如果內存中已經有圖片緩存,SDImageCacheDelegate 回調 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
- SDWebImageManagerDelegate 回調 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示圖片。
- 如果內存緩存中沒有,生成 NSInvocationOperation 添加到隊列開始從硬盤查找圖片是否已經緩存。
- 根據 URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進行的操作,所以回主線程進行結果回調 notifyDelegate:
- 如果上一操作從硬盤讀取到了圖片,將圖片添加到內存緩存中(如果空閒內存過小,會先清空內存緩存)。SDImageCacheDelegate 回調 imageCache:didFindImage:forKey:userInfo:。進而回調展示圖片。
- 如果從硬盤緩存目錄讀取不到圖片,說明所有緩存都不存在該圖片,需要下載圖片,回調 imageCache:didNotFindImageForKey:userInfo:。
- 共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片。
- 圖片下載由 NSURLConnection 來做,實現相關 delegate 來判斷圖片下載中、下載完成和下載失敗。
- connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進度加載效果。
- connectionDidFinishLoading: 數據下載完成後交給 SDWebImageDecoder 做圖片解碼處理。
- 圖片解碼處理在一個 NSOperationQueue 完成,不會拖慢主線程
UI。如果有需要對下載的圖片進行二次處理,最好也在這裏完成,效率會好很多。 - 在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回調給 SDWebImageDownloader。
- imageDownloader:didFinishWithImage: 回調給 SDWebImageManager 告知圖片下載完成。
- 通知所有的 downloadDelegates 下載完成,回調給需要的地方展示圖片。
- 將圖片保存到 SDImageCache 中,內存緩存和硬盤緩存同時保存。寫文件到硬盤也在以單獨
NSInvocationOperation 完成,避免拖慢主線程。 - SDImageCache 在初始化的時候會註冊一些消息通知,在內存警告或退到後臺的時候清理內存圖片緩存,應用結束的時候清理過期圖片
- SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
- SDWebImagePrefetcher 可以預先下載圖片,方便後續使用。
FMDB
iOS 平臺上的SQLite數據庫框架, 以OC的方式封裝了SQLit的C語言API, 使用起來更加面向對象, 省去了很多麻煩/冗餘的C語言代碼, 對比蘋果自帶的Core Data框架更加輕量級和靈活, 並且提供了多線程的數據庫操作方法. 有效的防止了數據混亂 .
FMDB有三個主要的類:
- FMDataBase 簡介: 一個FMDataBase對象就代表一個單獨的SQLite數據庫
作用: 用來執行SQL語句 - FMResultSet
作用: 使用FMDataBase執行查詢後的結果集 - FMDataBaseQueue
作用:用於在多線程中執行多個查詢或者更新, 它是線程安全的:
- FMDataBase 簡介: 一個FMDataBase對象就代表一個單獨的SQLite數據庫
FMDB的簡單使用
- 通過SQLite數據庫文件路徑來創建FMDataBase對象
- 通過指定SQLite數據庫文件路徑來創建FMDatabase對象
打開數據庫
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@"數據庫打開失敗!");
}
文件路徑有三種情況
(1)具體文件路徑
如果不存在會自動創建
(2)空字符串@""
會在臨時目錄創建一個空的數據庫
當FMDatabase連接關閉時,數據庫文件也被刪除
(3)nil
會創建一個內存中臨時數據庫,當FMDatabase連接關閉時,數據庫會被銷燬
執行操作
打開數據庫
//1 獲取數據庫文件路徑
NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *fileName = [document stringByAppendingPathComponent:@"stu.sqlite"];
//2 獲取數據庫
FMDatabase *dataBase = [FMDatabase databaseWithPath:fileName];
//3 打開數據庫
if ([dataBase open]) {
//4 創建表
BOOL result = [dataBase executeUpdate:@"create table if not exists t_student(id integer primary key autoinerement, name text not null , age integer not null)"];
if (result) {
NSLog(@"YES");
self.database = dataBase;
}else
{
NSLog(@"NO");
}
}
插入數據
NSString *name = [NSString stringWithFormat:@"%d",arc4random() % 10];
[self.database executeUpdate:@"insert into t_student (name, age) value(?,?);",name,@(arc4random_uniform(40))];
刪除數據
BOOL result = [self.databaseexecuteUpdate:@"delete from t_student where name=4"];
NSLog(@"%d",result);
修改數據
BOOL result = [self.databaseexecuteUpdate:@"update t_student set name='ICE' where name = 3"];
NSLog(@"%d",result);
查詢數據
FMResultSet *resultSet = [self.databaseexecuteQuery:@"select * from t_student"];
//便利結果
while ([resultSet next]) {
NSString *name = [resultSet stringForColumn:@"name"];
int age = [resultSet intForColumn:@"age"];
NSLog(@"%@\n%d",name,age);
}
MJRefresh
MKNetworkKit
MKNetworkKit 是一個使用十分方便,功能又十分強大、完整的iOS網絡編程代碼庫,完全基於 ARC。它只有兩個類, 它的目標是使用像AFNetworking這麼簡單,而功能像ASIHTTPRequest(已經停止維護)那麼強大。
優點
1、高度的輕量級,僅僅只有2個主類;
2、自主操作多個網絡請求;
3、更加準確的顯示網絡活動指標;
4、自動設置網絡速度,實現自動的2G、3G、wifi切換;
5、自動緩衝技術的完美應用,實現網絡操作記憶功能,當你掉線了又上線後,會繼續執行未完成的網絡請求;
6、可以實現網絡請求的暫停功能;
7、準確無誤的成功執行一次網絡請求,摒棄後臺的多次請求浪費;
8、支持圖片緩衝;
9、支持ARC機制;
10、在整個app中可以只用一個隊列(queue),隊列的大小可以自動調整。
使用介紹
MKNetworkKit中主要有兩個類:MKNetworkOperation和MKNetworkEngine。MKNetworkOperation是NSOperation的子類並且封裝了請求相應類,我們需要爲每一個網絡請求創建一個MKNetworkOperation。MKNetworkEngine負責管理網絡隊列,對於簡單的請求,我們應該直接使用MKNetworkEngine的方法,對於複雜的需求,我們可以子類化MKNetworkEngine。下面就介紹基本的網絡實現,其中包括GET請求和POST請求:
如何實現請求
MKNetworkEngine *engine = [[MKNetworkEngine alloc] initWithHostName:@"www.***.net" customHeaderFields:nil];
MKNetworkOperation *op = [engine operationWithPath:@"json/conn.asp?id=235" params:nil httpMethod:@"GET"];
[op addCompletionHandler:^(MKNetworkOperation *completedOperation) {
NSLog(@"%@",[completedOperation responseString]);
} errorHandler:^(MKNetworkOperation *completedOperation, NSError *error) {
}];
MKNetworkEngine *engine = [[MKNetworkEngine alloc] initWithHostName:@"192.168.2.176:9502/api" customHeaderFields:nil];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"admin" forKey:@"username"];
[dic setValue:@"123" forKey:@"password"];
MKNetworkOperation *op = [engine operationWithPath:@"user.do" params:dic httpMethod:@"POST"];
[op addCompletionHandler:^(MKNetworkOperation *completedOperation) {
NSLog(@"%@",[completedOperation responseString]);
} errorHandler:^(MKNetworkOperation *completedOperation, NSError *error) {
}];
MBProgressHUD
MBProgressHUD 是一個現實HUD窗口的第三方類庫, 用於執行一些後臺任務時, 在程序中顯示一個進度的koading視圖和兩個可選的文本提示的HUD窗口. 我想最多是應用在加載網絡數據的時候。其實蘋果官方自己有一個帶有此功能的類UIProgressHUD,只不過它是私有的,現在不讓用。至於實際的效果,可以看看github上工程給出的幾張圖例(貌似我這經常無法單獨打開圖片,所以就不在這貼圖片了),也可以運行一下Demo。
具體用法我們就不多說了,參考github上的說明就能用得很順的。本文主要還是從源碼的角度來分析一下它的具體實現。
//方式1.直接在View上show
HUD = [[MBProgressHUD showHUDAddedTo:self.view animated:YES] retain];
HUD.delegate = self;
//常用的設置
//小矩形的背景色
HUD.color = [UIColor clearColor];//這兒表示無背景
//顯示的文字
HUD.labelText = @"Test";
//細節文字
HUD.detailsLabelText = @"Test detail";
//是否有庶罩
HUD.dimBackground = YES;
[HUD hide:YES afterDelay:2];
//只顯示文字
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeText;
hud.labelText = @"Some message...";
hud.margin = 10.f;
hud.yOffset = 150.f;
hud.removeFromSuperViewOnHide = YES;
[hud hide:YES afterDelay:3];
//方式2.initWithView
//use block
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.labelText = @"Test";
[HUD showAnimated:YES whileExecutingBlock:^{
NSLog(@"%@",@"do somethings....");
[self doTask];
} completionBlock:^{
[HUD removeFromSuperview];
[HUD release];
}];
//圓形進度條
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.mode = MBProgressHUDModeAnnularDeterminate;
HUD.delegate = self;
HUD.labelText = @"Loading";
[HUD showWhileExecuting:@selector(myProgressTask) onTarget:self withObject:nil animated:YES];
//自定義view
HUD = [[MBProgressHUD alloc] initWithView:self.view];
HUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]] autorelease];
// Set custom view mode
HUD.mode = MBProgressHUDModeCustomView;
HUD.delegate = self;
HUD.labelText = @"Completed";
[HUD show:YES];
[HUD hide:YES afterDelay:3];
代理方法:
[cpp] view plaincopy
#pragma mark -
#pragma mark HUD的代理方法,關閉HUD時執行
-(void)hudWasHidden:(MBProgressHUD *)hud
{
[hud removeFromSuperview];
[hud release];
hud = nil;
}
二個task
[cpp] view plaincopy
-(void) doTask{
//你要進行的一些邏輯操作
sleep(2);
}
-(void) myProgressTask{
float progress = 0.0f;
while (progress < 1.0f) {
progress += 0.01f;
HUD.progress = progress;
usleep(50000);
}
}