技 術(shù) 文 章 / 超 人
GET,POST基本帶參數(shù)網(wǎng)絡(luò)請求
//請求地址
NSURL *url = [NSURL URLWithString:URLString];
//設(shè)置請求地址
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//設(shè)置請求方式
request.HTTPMethod = @"POST";
//設(shè)置請求參數(shù)
request.HTTPBody = [parameters dataUsingEncoding:NSUTF8StringEncoding];
//關(guān)于parameters是NSDictionary拼接后的NSString.關(guān)于拼接看后面拼接方法說明
//設(shè)置請求session
NSURLSession *session = [NSURLSession sharedSession];
//設(shè)置網(wǎng)絡(luò)請求的返回接收器
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
if (failure) {
failure(error);
}
}else
{
NSError *error;
NSMutableDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (error) {
if (failure) {
failure(error);
}
}else
{
if (success) {
success(responseObject);
}
}
}
});
}];
//開始請求
[dataTask resume];
拼接parameters 參數(shù)
/**
拼接字典數(shù)據(jù)
@param parameters 參數(shù)
@return 拼接后的字符串
*/
-(NSString *)parameters:(NSDictionary *)parameters
{
//創(chuàng)建可變字符串來承載拼接后的參數(shù)
NSMutableString *parameterString = [NSMutableString new];
//獲取parameters中所有的key
NSArray *parameterArray = parameters.allKeys;
for (int i = 0;i < parameterArray.count;i++) {
//根據(jù)key取出所有的value
id value = parameters[parameterArray[i]];
//把parameters的key 和 value進行拼接
NSString *keyValue = [NSString stringWithFormat:@"%@=%@",parameterArray[i],value];
if (i == parameterArray.count || i == 0) {
//如果當(dāng)前參數(shù)是最后或者第一個參數(shù)就直接拼接到字符串后面,因為第一個參數(shù)和最后一個參數(shù)不需要加 “&”符號來標識拼接的參數(shù)
[parameterString appendString:keyValue];
}else
{
//拼接參數(shù)修赞, &表示與前面的參數(shù)拼接
[parameterString appendString:[NSString stringWithFormat:@"&%@",keyValue]];
}
}
return parameterString;
}
上傳文件原生請求
NSURLRequestCachePolicy 緩存枚舉說明
//指定緩存邏輯婶恼。URL加載系統(tǒng)提供了一個磁盤和內(nèi)存混合的緩存,來相應(yīng)網(wǎng)絡(luò)請求柏副。這個緩存允許一個應(yīng)用減少對網(wǎng)絡(luò)連接的依賴勾邦,并且增加性能。使用緩存的目的是為了使用的應(yīng)用程序能更快速的響應(yīng)用戶輸入割择,是程序高效的運行眷篇。有時候我們需要將遠程web服務(wù)器獲取的數(shù)據(jù)緩存起來,減少對同一個url多次請求荔泳。
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
NSURLRequestUseProtocolCachePolicy = 0,//默認緩存策略铅歼。具體工作:如果一個NSCachedURLResponse對于請求并不存在,數(shù)據(jù)將會從源端獲取换可。如果請求擁有一個緩存的響應(yīng)椎椰,那么URL加載系統(tǒng)會檢查這個響應(yīng)來決定,如果它指定內(nèi)容必須重新生效的話沾鳄。假如內(nèi)容必須重新生效慨飘,將建立一個連向源端的連接來查看內(nèi)容是否發(fā)生變化。假如內(nèi)容沒有變化译荞,那么響應(yīng)就從本地緩存返回數(shù)據(jù)瓤的。如果內(nèi)容變化了,那么數(shù)據(jù)將從源端獲取
NSURLRequestReloadIgnoringLocalCacheData = 1,// URL應(yīng)該加載源端數(shù)據(jù)吞歼,不使用本地緩存數(shù)據(jù)
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // 本地緩存數(shù)據(jù)圈膏、代理和其他中介都要忽視他們的緩存,直接加載源數(shù)據(jù)
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,//兩個的設(shè)置相同
NSURLRequestReturnCacheDataElseLoad = 2,//使用緩存數(shù)據(jù)篙骡,忽略其過期時間稽坤;只有在沒有緩存版本的時候才從源端加載數(shù)據(jù)。
NSURLRequestReturnCacheDataDontLoad = 3,//只使用cache數(shù)據(jù)糯俗,如果不存在cache尿褪,請求失敗得湘;用于沒有建立網(wǎng)絡(luò)連接離線模式
NSURLRequestReloadRevalidatingCacheData = 5, //指定如果已存的緩存數(shù)據(jù)被提供它的源段確認為有效則允許使用緩存數(shù)據(jù)響應(yīng)請求杖玲,否則從源段加載數(shù)據(jù)。
};
//只有響應(yīng)http和https的請求會被緩存淘正。ftp和文件協(xié)議當(dāng)被緩存策略允許的時候嘗試接入源段摆马。自定義的NSURLProtocol類能夠保護緩存臼闻,如果它們被選擇使用的話。
mimeType 文件類型
上傳文件請求
//指定NSMutableURLRequest的 url請求地址囤采、緩存機制述呐、超時時長
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval: self.timeoutInterval];
//指定加載進度的回調(diào)
self.progressBlock = upProgress;
/*
multipart/from-data 編碼類型,以提高二進制文件的傳輸效率斑唬。是一種進行表單提交時的消息格式市埋。表單提交數(shù)據(jù)的時候,默認類型是application/x-www-form-urlencoded恕刘,也就是key=value的鍵值對格式缤谎,提交文件的時候使用multipart/from-data。因為是表單提交褐着,所以http請求方式是POST坷澡。然后在請求頭里設(shè)置Content-Type為multipart/from-data指定請求的格式
charset=utf-8 編碼格式
boundary 分隔符,分隔多個文件含蓉、表單項频敛。確保整個分隔符不會在文件或表單項的內(nèi)容中出現(xiàn)。
*/
//設(shè)置HTTPHeader中Content-Type的值
[request setValue:[[NSString alloc] initWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@",self.boundary] forHTTPHeaderField:@"Content-Type"];
//請求方式
request.HTTPMethod = @"POST";
/*
parameters 請求參數(shù)
fileData 上傳的文件 NSData類型
name 文件名馅扣,一般隨意取或與服務(wù)器協(xié)商
fileName 文件加后綴名斟赚,例如傳圖片 就取 test.jpg 一般隨意取或與服務(wù)器協(xié)商
mimeType 文件類型
*/
//該方法拼接上傳文件的 Data數(shù)據(jù)
NSData * payloadData = [self setBodydataWithParameters:parameters fileData:fileData name:name fileName:fileName mimeType:mimeType];
/* 1、defaultSessionConfiguration"返回標準配置差油,這實際上與NSURLConnection的網(wǎng)絡(luò)協(xié)議棧是一樣的拗军,具有相同的共享NSHTTPCookieStorage,共享NSURLCache和共享NSURLCredentialStorage蓄喇。
2发侵、 "ephemeralSessionConfiguration"返回一個預(yù)設(shè)配置,沒有持久性存儲的緩存妆偏,Cookie或證書刃鳄。這對于實現(xiàn)像"秘密瀏覽"功能的功能來說,是很理想的钱骂。
3叔锐、 "backgroundSessionConfiguration":獨特之處在于,它會創(chuàng)建一個后臺會話罐柳。后臺會話不同于常規(guī)的掌腰,普通的會話,它甚至可以在應(yīng)用程序掛起张吉,退出,崩潰的情況下運行上傳和下載任務(wù)催植。初始化時指定的標識符肮蛹,被用于向任何可能在進程外恢復(fù)后臺傳輸?shù)氖刈o進程提供上下文勺择。
* /
//NSURLSessionConfiguration對象用于初始化NSURLSession對象
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
//如果要使用代理方法,需要設(shè)置代理,但從NSURLSession的頭文件發(fā)現(xiàn)session的delegate屬性是只讀的.因此設(shè)置代理要通過session的初始化方法賦,delegateQueue參數(shù)表示協(xié)議方法將會在哪個隊列(NSOperationQueue)里面執(zhí)行.
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
NSURLSessionUploadTask * uploadtask = [session uploadTaskWithRequest:request fromData:payloadData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!error) {
NSError *jserror = nil;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jserror];
if (jserror) {
if (failure){
failure(jserror);
}
}else if (success) {
success(dic);
}
}else if (failure){
failure(error);
}
});
}];
//開始請求
[uploadtask resume];
上傳文件Data拼接方法
/**
文件Data拼接
@param parameter 上傳參數(shù)
@param data 文件源
@param name 文件名
@param fileName 文件加后綴的具體名稱
@param mimeType 文件類型
@return 拼接后的Data
*/
- (NSData *)setBodydataWithParameters:(NSDictionary *)parameter
fileData:(NSData *)data
name:(NSString *)name
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType
{
NSData * imageData = data;
//1.構(gòu)造body string
NSMutableString *bodyString = [[NSMutableString alloc] init];
//2.拼接body string
NSMutableData *bodyData = [NSMutableData data];
[parameter enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
[bodyString appendFormat:@"--%@\r\n", self.boundary];
[bodyString appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
[bodyString appendFormat:@"%@\r\n",obj];
}];
[bodyString appendFormat:@"--%@\r\n", self.boundary];
[bodyString appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",name,fileName];
[bodyString appendFormat:@"Content-Type: %@\r\n\r\n",mimeType];
//拼接的過程
//前面的bodyString, 其他參數(shù)
[bodyData appendData:[bodyString dataUsingEncoding:NSUTF8StringEncoding]];
//圖片數(shù)據(jù)
[bodyData appendData:imageData];
//4.結(jié)束的分隔線
NSString *endStr = [NSString stringWithFormat:@"\r\n--%@--\r\n",self.boundary];
//拼接到bodyData最后面
[bodyData appendData:[endStr dataUsingEncoding:NSUTF8StringEncoding]];
return bodyData;
}
關(guān)于NSURLSessionDelegate
上傳進度獲取
/*
調(diào)用該方法上傳文件數(shù)據(jù)
如果文件數(shù)據(jù)很大伦忠,那么該方法會被調(diào)用多次
參數(shù)說明:
totalBytesSent:已經(jīng)上傳的文件數(shù)據(jù)的大小
totalBytesExpectedToSend:文件的總大小
*/
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
self.uploadProgress.totalUnitCount = totalBytesExpectedToSend;
self.uploadProgress.completedUnitCount = totalBytesSent;
//這里的progressBlock省核、uploadProgress都是自己定義的回調(diào)。上面上傳文件中也有設(shè)置
self.progressBlock(self.uploadProgress) ;
}
參考資料:
1.NSURLSession使用說明及后臺工作流程分析
2.iOS開發(fā)之網(wǎng)絡(luò)編程--6昆码、NSURLSessionConfiguration筆記
3.使用NSURLSession