現現在單機版本的 APP 幾乎不復存在,咱們須要掌握如何使用 iOS/web/Android 如何發送 http/https 請求給後端服務,根據響應數據渲染頁面。本文主要介紹如何使用 iOS 創建網絡請求。html
要實現網絡請求須要經歷以下幾個步驟:java
一個請求百度首頁圖片的例子:ios
- (void) network{
// 1. 建立一個url
NSURL *url= [NSURL URLWithString: @"https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"];
// 2. 建立一個網絡請求,網絡請求不指定方法默認是GET
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
// request.HTTPMethod = @"GET";
// 自定義請求配置
// NSURLSessionConfiguration *config = [[NSURLSessionConfiguration alloc] init];
// config.timeoutIntervalForRequest= 20;// 請求超超時時間
// //...還有不少參數
// NSURLSession *session = [NSURLSession sessionWithConfiguration: config];
// 3. 建立網絡管理
NSURLSession *session = [NSURLSession sharedSession];
// 4. 建立一個網絡任務
/* 第一個參數 : 請求對象 第二個參數 : completionHandler回調 ( 請求完成 ["成功"or"失敗"] 的回調 ) data : 響應體信息(指望的數據) response : 響應頭信息,主要是對服務器端的描述 error : 錯誤信息 , 若是請求失敗 , 則error有值 */
NSURLSessionDataTask *task= [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// data就是服務器返回的數據,response爲服務器的響應
if(!error){
// 強轉爲NSHTTPURLResponse
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
if(res.statusCode == 200){
// 更新UI必須回到主線程
dispatch_async(dispatch_get_main_queue(), ^{
self.imgView.image = [UIImage imageWithData:data];
});
}
}else{
NSLog(@"報錯啦,%@",error);
}
}];
// 5. 開啓任務
[task resume];
}
複製代碼
若是你把上面的 https 請求更換成 http,你會發現以下報錯:git
報錯啦,Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSUnderlyingError=0x60000246d4d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1022 "(null)"}, NSErrorFailingURLStringKey=http://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png, NSErrorFailingURLKey=http://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.
複製代碼
其主要緣由是 iOS 默認使用 https 請求,而不是 http;因此會攔截 http 請求,因此會報錯。github
要保證 iOS 可以訪問 http 請求;須要在 Info.plist 文件中新增以下配置:web
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
複製代碼
這裏使用一個真實的環境,請求 json 數據,返回轉換成 Model 並天氣列表。主要步驟以下:編程
#import "ViewController.h"
#import "Weather.h"
#import "WeatherCell.h"
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) NSMutableArray<Weather *> * weathers;
@property (weak, nonatomic) IBOutlet UITableView *weatherTableView;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator;
@end
@implementation ViewController
-(NSMutableArray<Weather *> *)weathers{
if (_weathers == nil) {
// 須要初始化weathers,防止不存在數據,調用weathers.count等報錯
_weathers = [NSMutableArray arrayWithCapacity:7];
}
return _weathers;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 設置行高,防止展現高度不足
self.weatherTableView.rowHeight = 100.0;
// 刪除Tableview底部的空白區域
self.weatherTableView.tableFooterView = [[UIView alloc]init];
[self weather];
}
-(void)weather{
//1.建立一個url
NSString *net = @"http://v.juhe.cn/weather/index?format=2&cityname=重慶&key=2d2e6e836dbdffac56814bc4d449d507";
//帶中文的url進行轉換
net = [net stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:net];
//2.建立一個網絡請求(url)
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
//request.HTTPMethod = @"POST";
// 自定義請求配置
// NSURLSessionConfiguration *config = [[NSURLSessionConfiguration alloc] init];
// config.timeoutIntervalForRequest= 20;// 請求超超時時間
// //...還有不少參數
// NSURLSession *session = [NSURLSession sessionWithConfiguration: config];
//3.建立網絡管理,
NSURLSession *session = [NSURLSession sharedSession];
//4.建立一個網絡任務
NSURLSessionDataTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"有錯誤");
}
else {
//須要轉換成NSHTTPURLResponse
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
NSLog(@"%ld", (long)res.statusCode);
/** NSJSONReadingOptions
* NSJSONReadingMutableContainers = (1UL << 0),
* 容器可變,NSMutableDictionary 或NSMutableArray。
*
* NSJSONReadingMutableLeaves = (1UL << 1),
* 葉子可變,返回的 JSON 對象中字符串的值爲 NSMutableString。
*
* NSJSONReadingAllowFragments = (1UL << 2)
* 容許 JSON 字符串最外層既不是 NSArray 也不是 NSDictionary,但必須是有效的 JSON 片斷
*/
//JSON(字典)轉模型
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
//取將來7每天氣
NSArray *future = dic[@"result"][@"future"];
for(int i = 0; i < future.count; i++){
NSDictionary *wd = future[i];
// 此處建立Weather還有優化空間,詳情請見下一節 使用KVC的方式優化json轉換Model
Weather *w = [[Weather alloc]init];
w.temperature = wd[@"temperature"];
w.weather = wd[@"weather"];
w.wind = wd[@"wind"];
w.week = wd[@"week"];
w.date_y = wd[@"date"];
[self.weathers addObject:w];
}
NSLog(@"%ld", self.weathers.count);
//默認網絡請求在自線程 更新界面要回到主線程
dispatch_async(dispatch_get_main_queue(), ^{
// 模擬加載數據2s,加一點進度條;現實狀況是不須要的
[NSThread sleepForTimeInterval:2.0];
//刷新界面
[self.weatherTableView reloadData];
[self.indicator stopAnimating];
});
}
}];
//5.開啓任務
[task resume];
}
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
WeatherCell *cell = [tableView dequeueReusableCellWithIdentifier:@"weather"];
cell.w = self.weathers[indexPath.row];
return cell;
}
- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.weathers.count;
}
@end
複製代碼
上面的代碼展現瞭如何請求網絡並展現列表,列表如何展現詳情請見:iOS 開發-非徹底指南之: TableView 的使用詳解json
此處的案例是基於上面的 json 請求;前面再獲取到 json 數據轉換成 NSDictonaray,須要本身手動的建立 Weather 並讀取 Key 賦值,在真實的場景下很容易將字段的 key 值寫錯,因此咱們須要使用到 KVC 的方式賦值。後端
優化前的代碼bash
for(int i = 0; i < future.count; i++){
NSDictionary *wd = future[i];
Weather *w = [[Weather alloc]init];
w.temperature = wd[@"temperature"];
w.weather = wd[@"weather"];
w.wind = wd[@"wind"];
w.week = wd[@"week"];
w.date_y = wd[@"date"];
[self.weathers addObject:w];
}
複製代碼
優化後的代碼
for(int i = 0; i < future.count; i++){
NSDictionary *wd = future[i];
Weather *w = [[Weather alloc] initWithDictionary:wd];
[self.weathers addObject:w];
}
複製代碼
須要在 Weath 中構造一個initWithDictionary
初始化函數:
//
// Weather.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Weather : NSObject
@property (nonatomic, copy) NSString * temperature;
@property (nonatomic, copy) NSString * weather;
@property (nonatomic, copy) NSString * wind;
@property (nonatomic, copy) NSString * week;
@property (nonatomic, copy) NSString * date_y;
- (instancetype)initWithDictionary:(NSDictionary *) dic; // 新增的
@end
NS_ASSUME_NONNULL_END
複製代碼
而後在 Weather.m 中實現其函數
//
// Weather.m
#import "Weather.h"
@implementation Weather
-(instancetype)initWithDictionary:(NSDictionary *)dic {
if (self = [super init]) {
// 使用KVC的方式給屬性賦值,直接將key給Model中的key
[self setValuesForKeysWithDictionary:dic];
}
return self;
}
//屬性與字典不匹配時進行改正,不改的話不會崩潰但拿不到值
- (void)setValue:(id)value forKey:(NSString *)key{
//在這裏更改key
if([key isEqualToString:@"date"]){
key = @"date_y";
}
[super setValue:value forKey:key];
}
//冗錯處理,若是有未定義的字段的話就會走到這裏,不重寫的話會引發崩潰
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"value:%@,undefineKey:%@",value,key);
}
@end
複製代碼
總結:
setValuesForKeysWithDictionary
將字典中的 key 和 value 映射到咱們的 Model 中;setValuesForKeysWithDictionary
使用前提是返回的 json 和 Model 的屬性相同/相似的狀況;setValue,forKey
以及不須要的字段 forUndefinedKey
setValue,forKey
進行轉換發送 POST 網絡請求,主要流程和 GET 請求相似,主要差別在構建NSURLRequest
的部分;一個簡單的例子以下:
//1.建立可變的請求對象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//2.修改請求方法爲POST
request.HTTPMethod = @"POST";
//4.設置請求體信息,字符串--->NSData
request.HTTPBody = [@"username=mrgaogang&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];
複製代碼
寫在前面: 建議使用 AFNetworking 的文件下載
使用原生的方式實現文件下載主要有以下幾個步驟:
sessionWithConfiguration
建立 Session 對象,並設置請求代理NSURLSessionTaskDelegate
和隊列
downloadTask bytesWritten totalBytesWritten
downloadTask didFinishDownloadingToURL
downloadTaskWithRequest
下載文件一個簡單的例子:
#import "ViewController.h"
@interface ViewController () <NSURLSessionDownloadDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *downloadProgress;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 1.肯定URL
NSURL *url = [NSURL URLWithString:@"http://localhost:8080/AppTestAPI/wall.png"];
// 2.建立請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3.建立會話對象
//NSURLSession *session = [NSURLSession sharedSession];
// Configuration:配置信息,用默認的便可;將下載的代理方法設置爲self並設置爲主隊列
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
[downloadTask resume];// 執行Task
}
/**
1.寫數據(監聽下載進度)
session 會話對象
downloadTask 下載任務
bytesWritten 本次寫入的數據大小
totalBytesWritten 下載的數據總大小
totalBytesExpectedToWrite 文件的總大小
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
self.downloadProgress.progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;
}
/**
3.當下載完成的時候調用
location 文件的臨時存儲路徑,在沙盒中的tmp目錄下
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
// 1.拼接文件全路徑
// downloadTask.response.suggestedFilename 文件名稱
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
// 2.剪切文件
[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
NSLog(@"%@",fullPath);
}
@end
複製代碼
寫在前面:建議使用 AFNetworking 的文件上傳功能
原生的文件上傳功能比較複雜,主要分爲以下幾個步驟:
Content-Type
等NSURLSessionTaskDelegate
並實現以下方法task didSendBodyData totalBytesSent
task didCompleteWithError
uploadTaskWithRequest
fromData
包括啓動標記,文件參數和結束標記一個簡單的例子:
#import "ViewController.h"
@interface ViewController ()<NSURLSessionTaskDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:@"上傳的url"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
NSString *httpHead = [NSString stringWithFormat:@"multipart/form-data;boundary=----WebKitFormBoundaryUFNaH6losNxu4xDq"];
//設置請求的頭 告訴服務器我要上傳數據
[request setValue:httpHead forHTTPHeaderField:@"Content-Type"];
request.HTTPMethod = @"POST";
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//fromData:就是要上傳的數據
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:[self getData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
[task resume];
}
-(NSData *)getData
{
/******************************************************************/
// 設置請求體
// 設置請求體
// 給請求體加入固定格式數據 這裏也是使用的也是可變的,由於多嘛
NSMutableData *data = [NSMutableData data];
// 開始標記
// boundary
[data appendData:[@"------WebKitFormBoundaryUFNaH6losNxu4xDq" dataUsingEncoding:NSUTF8StringEncoding]];
// \r\n換行符
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// Content-Disposition: form-data; name="myfile"; filename="wall.jpg"
[data appendData:[@"Content-Disposition: form-data; name=\"myfile\"; filename=\"123.jpg\"" dataUsingEncoding:NSUTF8StringEncoding]];
// \r\n換行符
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// Content-Type 上傳文件的MIME
[data appendData:[@"Content-Type: image/jpeg" dataUsingEncoding:NSUTF8StringEncoding]];
// 兩個換行符
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 上傳文件參數
//圖片數據 而且轉換爲Data
UIImage *image = [UIImage imageNamed:@"wall.jpg"];
NSData *imagedata = UIImageJPEGRepresentation(image, 1.0);
[data appendData:imagedata];
//若是是PNG圖片須要修改上面幾個地方 數據格式以下
// UIImage *image2 = [UIImage imageNamed:@"wall2"];
// NSData *imagedata2 = UIImagePNGRepresentation(image2);
// [data appendData:imagedata2];
//
//若是上傳的是zip壓縮包
//NSString *path = [[NSBundle mainBundle] pathForResource:@"wall.zip" ofType:nil];
//[data appendData:[NSData dataWithContentsOfFile:path]];
// 兩個換行符
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 添加結束標記
// \r\n換行符
[data appendData:[@"------WebKitFormBoundaryUFNaH6losNxu4xDq--" dataUsingEncoding:NSUTF8StringEncoding]];
// boundary
[data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
return data;
}
/*
只要給服務器上傳數據就會調用 (一次或屢次)
bytesSent: 當前這一次發送的數據長度
totalBytesSent: 總共已經發送的數據長度
totalBytesExpectedToSend: 須要上傳的文件的總大小
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
NSLog(@"%lld", 100 * totalBytesSent / totalBytesExpectedToSend);
}
/*
判斷是否上傳成功,若是失敗error是具備值
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"%s, %@", __func__, error);
}
@end
複製代碼
AFNetworking 的使用相比原生請求主要有以下差別:
NSURLSessionConfiguration
並自定義了 NSURLSessionAFURLSessionManager
封裝了文件上傳,下載及斷點續傳和普通的網絡請求-(void)weather{
//建立管理者
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
//建立網絡請求
NSString *net = @"http://v.juhe.cn/weather/index?format=2&cityname=重慶&key=2d2e6e836dbdffac56814bc4d449d507";
net = [net stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *URL = [NSURL URLWithString:net];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
//建立任務
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
} downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
//須要轉換成NSHTTPURLResponse
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
NSLog(@"%ld", (long)res.statusCode);
NSLog(@"%@ %@", response, responseObject);
// 網絡請求直接返回響應後轉換的數據responseObject,無需本身手動轉換
//取將來7每天氣
NSArray *future = responseObject[@"result"][@"future"];
for(int i = 0; i < future.count; i++){
NSDictionary *wd = future[i];
Weather *w = [[Weather alloc]initWithDictionary:wd];
[self.weathers addObject:w];
}
//刷新界面,無需回到主線程
[self.weatherTableView reloadData];
[self.indicator stopAnimating];
}
}];
//啓動任務
[dataTask resume];
}
複製代碼
注意點:
uploadTaskWithRequest
完成上傳可使用 process 監聽上傳進度NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Success: %@ %@", response, responseObject);
}
}];
[uploadTask resume];
複製代碼
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2529366712,3648628205&fm=26&gp=0.jpg"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
// 此處將文件存儲在沙盒中的Document中名稱就使用建議的名稱,也就是文件默認的名稱
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
// 或者使用NSSearchPathForDirectoriesInDomains的方式
// NSString *documentsDirectoryURL = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// NSString *fileUrl = [documentsDirectoryURL stringByAppendingPathComponent:response.suggestedFilename];
// NSURL *url = [NSURL fileURLWithPath:fileUrl]; // 注意此處必須是fileURLWithPath
// 此處將文件存儲在沙盒中的Document中名稱就使用建議的名稱,也就是文件默認的名稱
// return url;
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];
複製代碼
請求支持 NSDictionary 不須要再使用?拼接;也支持 POST 請求 HTTPBody
NSString *URLString = @"http://example.com";
NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]};
複製代碼
JSON 類型
[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters error:nil];
複製代碼
POST http://example.com/
Content-Type: application/json
{"foo": "bar", "baz": [1,2,3]}
複製代碼
query 參數類型
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters error:nil];
複製代碼
GET http://example.com?foo=bar&baz[]=1&baz[]=2&baz[]=3
複製代碼
表單類型
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters error:nil];
複製代碼
POST http://example.com/
Content-Type: application/x-www-form-urlencoded
foo=bar&baz[]=1&baz[]=2&baz[]=3
複製代碼
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusNotReachable: //沒網絡
break;
case AFNetworkReachabilityStatusReachableViaWiFi://WIFI代碼
break;
case AFNetworkReachabilityStatusReachableViaWWAN: //蜂窩移動數據
break;
default:
break;
}
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
複製代碼
網絡狀態 status 有:
SDWebImage 是一個 iOS 端的圖片加載庫。
#import "SDWebImage/UIImageView+WebCache.h"
//經過SDWebImage加載圖片
NSURL *url = [NSURL URLWithString:@"https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1571140150,993479906&fm=26&gp=0.jpg"];
[self.icon sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"rain"]];
複製代碼
Gift 圖片
SDAnimatedImageView *imageView = [SDAnimatedImageView new];
SDAnimatedImage *animatedImage = [SDAnimatedImage imageNamed:@"image.gif"];
imageView.image = animatedImage;
複製代碼
MJRefresh 實在是太強大了,不只僅是下拉刷新,還有上拉加載,指定位置刷新等,建議看官方文檔
參考