深入解析POST上傳-->AFNetworking的底層理解

一. POST單文件上傳-簡單使用

1. 創(chuàng)建請求

  • 實(shí)例化請求并設(shè)置基本參數(shù)
    // 0. 獲取服務(wù)器端口的地址
    NSURL *url = [NSURL URLWithString:@"http://localhost/upload/upload.php"];

    #warning:對于POST請求缘厢,必須手動設(shè)置其請求方法,因此要使用可變請求
    // 1. 創(chuàng)建請求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    // 2. 設(shè)置請求方式
    request.HTTPMethod = @"POST";

    // 3. 告訴服務(wù)器本次上傳文件的相關(guān)信息
    // 固定格式: 設(shè)置Content-Type
    // Content-Type: multipart/form-data; boundary=---------------------------198596859919834017191791522499
    // Content-Type:本次上傳文件類型信息,包含boundary
    // boundary:本次上傳文件的邊界(自己隨意設(shè)置垃环,只要三個地方一致即可)
    NSString *type = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kBoundary];
    [request setValue:type forHTTPHeaderField:@"Content-Type"];
  • 重難點(diǎn): 設(shè)置請求體筒捺,分為三個部分
    • 上邊界部分,告訴服務(wù)器要做數(shù)據(jù)上傳,包含了

      • userfile -> 負(fù)責(zé)上傳文件腳本中的 字段名,開發(fā)的時候,可以咨詢后端程序員
      • filename -> 將文件保存在服務(wù)器上的文件名稱
      • Content-Type -> 客戶端告訴服務(wù)器上傳文件的文件類型(如果不想寫文件類型,統(tǒng)一用 application/octet-stream[8進(jìn)制流])
    • 上傳文件的數(shù)據(jù)部分(即文件內(nèi)容的二進(jìn)制數(shù)據(jù))

    • 下邊界部分,嚴(yán)格按照字符串格式來設(shè)置:--boundary--

    // 實(shí)例化請求體
    NSMutableData *data = [NSMutableData data];

//    -----------------------------198596859919834017191791522499
//    Content-Disposition: form-data; name="userfile"; filename="WPFNetWorkTool.h"
//    Content-Type: application/octet-stream
#warning 有些服務(wù)器可以直接使用 \n回窘,但是新浪微博如果使用 \n 上傳文件坡氯,服務(wù)器會返回“沒有權(quán)限”的錯誤! 因此一定要注意安全換行:\r\n
    // 1. 拼接上傳文件的上邊界信息
    NSMutableString *headerStrM = [NSMutableString stringWithFormat:@"\r\n--%@\r\n", kBoundary];

    // name=%@ :服務(wù)器接收參數(shù)的key值帜羊,后臺工作人員告訴我們
    // filename=%@ :文件上傳到服務(wù)器的存儲名咒程,若不設(shè)置則為默認(rèn)名,名稱保持不變
    [headerStrM appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n", @"userfile", @"123" ];

    // Content-Type: application/octet-stream 表明文件的上傳類型讼育,亂寫類型不會影響上傳帐姻,但是不符合規(guī)范
    [headerStrM appendString:@"Content-Type: application/octet-stream\r\n\r\n"];

    // 將上傳文件的上邊界信息添加到請求體中
    [data appendData:[headerStrM dataUsingEncoding:NSUTF8StringEncoding]];

    // 2. 設(shè)置文件內(nèi)容
    // 文件地址
    NSString *filePath = @"/Users/wangpengfei/Desktop/WPFNetWorkTool.h";

    // 將文件轉(zhuǎn)化為二進(jìn)制形式
    NSData *fileData = [NSData dataWithContentsOfFile:filePath];

    // 將文件內(nèi)容添加到請求體中
    [data appendData:fileData];

    // 3. 設(shè)置文件的下邊界
    // -----------------------------198596859919834017191791522499--
    NSString *footerStrM = [NSString stringWithFormat:@"\r\n--%@--", kBoundary];

    NSLog(@"footerStrM--->%@", footerStrM);

    // 將下邊界添加到請求體中
    [data appendData:[footerStrM dataUsingEncoding:NSUTF8StringEncoding]];

    // 4. 設(shè)置請求體
    request.HTTPBody = data;

常見的 Content-Type 類型:

大類型 小類型
image png
image jpg
image gif
text html
application json

2. 發(fā)送請求

[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        /*
        打印結(jié)果:
            {"userfile":{"name":"123","type":"application\/octet-stream","tmp_name":"\/private\/var\/tmp\/phpEk0KCK","error":0,"size":0}}
        */

    }] resume];

二. POST單文件上傳-簡單封裝結(jié)構(gòu)體

1. 獲得本地文件響應(yīng)頭信息,使用同步方法*重難點(diǎn)*

通過響應(yīng)頭信息,可以獲得文件的類型/長度/建議的名稱.
  • MIMEType :就是文件類型
  • suggestedFilename : 推薦文件名(本地存儲名)
  • expectedContentLength : 文件長度

如果文件比較大,不建議發(fā)送本地請求.發(fā)送本地請求,會將文件從沙盒中加載到內(nèi)存中,造成內(nèi)存開銷.

    - (NSURLResponse *)getFileResponseWithFilePath:(NSString *)filePath {
    // 動態(tài)獲取文件類型

    // 1. 獲取文件路徑奶段,根據(jù)路徑獲取 url 地址饥瓷,本地協(xié)議名  file://
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@", filePath]];

    // 2. 創(chuàng)建請求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    // NSURLSession 沒有同步請求的方法
    // 利用 NSURLConnection 發(fā)送同步請求

    // 定義一片空的地址
    NSURLResponse *response = nil;

    // &response 二級指針
    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];

    return response;
}

2. 封裝請求體格式

  • filePath : 上傳文件的路徑
  • fileKey : 服務(wù)器接受文件的 key 值
  • fileName : 上傳文件在服務(wù)器中保存的名稱(可選)
    - (NSData *)setupHttpBodyWithFilePath:(NSString *)filePath fileKey:(NSString *)fileKey fileName:(NSString *)fileName;
  • 當(dāng)用戶沒有設(shè)置fileName時,調(diào)用方法一:設(shè)置文件為默認(rèn)名
    // 調(diào)用獲得本地文件信息的方法
    NSURLResponse *response = [self getFileResponseWithFilePath:filePath];

    if (!fileName) {
        fileName = response.suggestedFilename;
    }

三. POST單文件上傳封裝

1. 取出已封裝好的單例類WPFNetWorkTool,封裝以下方法

  • urlString:網(wǎng)絡(luò)接口
  • filePath:需要上傳的文件路徑
  • fileKey:服務(wù)器接收用戶上傳文件的key值
  • fileName:上傳文件存儲到服務(wù)器的名稱
  • success:上傳成功時調(diào)用的block
  • fail:上傳失敗時調(diào)用的block
    - (void)POSTFileWithUrlString:(NSString *)urlString
     filePath:(NSString *)filePath fileKey:(NSString *)fileKey
     fileName:(NSString *)fileName
     success:(successBlock)success fail:(failBlock)fail;

2. 在發(fā)送請求方法中增加以下內(nèi)容

[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 成功
        if (data && !error) {
            id responseObj = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
            // 如果不能解析JSON數(shù)據(jù)
            if (!responseObj) {
                responseObj = data;
            }
            // 執(zhí)行回調(diào)
            if (success) {
                success(responseObj, response);
            }
        // 失敗
        } else {
            // 執(zhí)行回調(diào)
            if (fail) {
                fail(error);
            }
        }
    }] resume];

3. 封裝方法的調(diào)用

// POST文件上傳
[[WPFNetWorkTool sharedTool] POSTFileWithUrlString:@"http://localhost/upload/upload.php" filePath:@"/Users/wangpengfei/Desktop/葵花寶典/下載工具/WPFNetWorkTool/WPFNetWorkTool.h" fileKey:@"userfile" fileName:NULL success:^(id obj, NSURLResponse *response) {
    NSLog(@"obj--->%@", obj);
} fail:^(NSError *error) {
    NSLog(@"error--->%@", error);
}];

#warning 圖片等文件可以顯示name痹籍,但是oc程序文件不能顯示
/*
打印結(jié)果:
    obj--->{
    userfile =     {
        error = 0;
        name = "(null)";
        size = 1702;
        "tmp_name" = "/private/var/tmp/phposR0Tv";
        type = "application/octet-stream";
    };
}
*/

四. POST多文件上傳-簡單使用

多文件上傳和單文件上傳的基本思路是一樣的,唯一的區(qū)別在于對請求體的封裝.

  • 多文件上傳的請求體格式

      // 第一個文件上邊界及參數(shù)
      \r\n--boundary\r\n
      Content-Disposition: form-data; name=userfile[]; filename=美女\r\n
      Content-Type:image/jpeg\r\n\r\n
    
      第一個文件的二進(jìn)制數(shù)據(jù)部分
    
      // 第二個文件上邊界及參數(shù)
      \r\n--boundary\r\n
      Content-Disposition: form-data; name=userfile[]; filename=JSON\r\n
      Content-Type:text/plain\r\n\r\n
    
      第二個文件的二進(jìn)制數(shù)據(jù)部分
    
      // 下邊界
      \r\n--boundary--
    
  • 1.設(shè)置第一個文件的上邊界及參數(shù)

    NSMutableString *headerStrM1 = [NSMutableString stringWithFormat:@"\r\n--%@\r\n", kBoundary];

    // name=%@ :服務(wù)器接收參數(shù)的key值呢铆,后臺工作人員告訴我們
    // filename=%@ :文件上傳到服務(wù)器的存儲名,若不設(shè)置則為默認(rèn)名蹲缠,名稱保持不變
#warning @"userfile[]"后臺人員提供的數(shù)據(jù)
    [headerStrM1 appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n", @"userfile[]", @"234" ];

    // Content-Type: application/octet-stream 表明文件的上傳類型棺克,亂寫類型不會影響上傳悠垛,但是不符合規(guī)范
    [headerStrM1 appendString:@"Content-Type: application/octet-stream\r\n\r\n"];

    // 將上傳文件的上邊界信息添加到請求體中
    [data appendData:[headerStrM1 dataUsingEncoding:NSUTF8StringEncoding]];
  • 2.設(shè)置第一個文件的二進(jìn)制數(shù)據(jù)
    // 文件地址
    NSString *filePath1 = @"/Users/wangpengfei/Desktop/photo/IMG_5544.jpg";

    // 將文件轉(zhuǎn)化為二進(jìn)制形式
    NSData *fileData1 = [NSData dataWithContentsOfFile:filePath1];

    // 將文件內(nèi)容添加到請求體中
    [data appendData:fileData1];
  • 3.設(shè)置第二個文件的上邊界及參數(shù)
NSMutableString *headerStrM2 = [NSMutableString stringWithFormat:@"\r\n--%@\r\n", kBoundary];

    // name=%@ :服務(wù)器接收參數(shù)的key值,后臺工作人員告訴我們
    // filename=%@ :文件上傳到服務(wù)器的存儲名娜谊,若不設(shè)置則為默認(rèn)名确买,名稱保持不變

    [headerStrM2 appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n", @"userfile[]", @"123" ];

    [headerStrM2 appendString:@"Content-Type: application/octet-stream\r\n\r\n"];

    // 將上傳文件的上邊界信息添加到請求體中
    [data appendData:[headerStrM2 dataUsingEncoding:NSUTF8StringEncoding]];
  • 4.設(shè)置第二個文件的二進(jìn)制數(shù)據(jù)
// 文件地址
    NSString *filePath2 = @"/Users/wangpengfei/Desktop/photo/beauty1.jpg";

    // 將文件轉(zhuǎn)化為二進(jìn)制形式
    NSData *fileData2 = [NSData dataWithContentsOfFile:filePath2];

    // 將文件內(nèi)容添加到請求體中
    [data appendData:fileData2];
  • 5.設(shè)置下邊界
    NSString *footerStrM = [NSString stringWithFormat:@"\r\n--%@--", kBoundary];

    // 將下邊界添加到請求體中
    [data appendData:[footerStrM dataUsingEncoding:NSUTF8StringEncoding]];

五. POST多文件上傳-添加普通參數(shù)

  • 有些網(wǎng)絡(luò)請求,客戶端需要告訴服務(wù)器一些必要的數(shù)據(jù),服務(wù)器根據(jù)客戶端傳過來的數(shù)據(jù)(參數(shù))去數(shù)據(jù)庫檢索出對應(yīng)的數(shù)據(jù).返回給客戶端.
  • 必須參數(shù): 必須附帶的參數(shù)(登錄時候的賬號和密碼).
  • 可選參數(shù): 可以自由選擇是否告訴給服務(wù)器的參數(shù).
  • 典型應(yīng)用:
    • 新浪微博: 上傳圖片的同時,發(fā)送一條微博信息!
    • 購物評論: 購買商品之后發(fā)表評論的時候圖片+評論內(nèi)容!
  • 多個參數(shù)之間以 & 分割.參數(shù)是'無序'的.
  • 大公司: 能夠附帶參數(shù),就會盡量多的附帶參數(shù).網(wǎng)絡(luò)監(jiān)測大數(shù)據(jù)開發(fā)/頁面檢測都必須由客戶端發(fā)送參數(shù)給服務(wù)器.

普通參數(shù)的格式如下:

-----------------------------16778832101575341713442286528
Content-Disposition: form-data; name="username"

Wpf

普通參數(shù)添加的位置:最后一個文件的二進(jìn)制內(nèi)容下邊界之間

使用一個可變字符串連接所有參數(shù)的全部信息(上邊界和具體內(nèi)容),然后統(tǒng)一轉(zhuǎn)化為二進(jìn)制形式

  • 設(shè)置第一個參數(shù)的上邊界
    NSMutableString *parameterStr = [NSMutableString stringWithFormat:@"\r\n--%@\r\n", kBoundary];
    // name=%@ :服務(wù)器接收普通文本參數(shù)的key值.后端人員告訴我們.
    // 文本參數(shù)也有可能有多個...
    [parameterStr appendFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n", @"username"];
  • 設(shè)置第一個參數(shù)的內(nèi)容
    [parameterStr appendString:@"WangPengfei"];
  • 設(shè)置第二個參數(shù)的上邊界
    [parameterStr appendFormat:@"\r\n--%@\r\n", kBoundary];
    [parameterStr appendFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n", @"password"];
  • 設(shè)置第二個參數(shù)的內(nèi)容
    [parameterStr appendString:@"123321"];
  • 統(tǒng)一轉(zhuǎn)化為二進(jìn)制形式
    [data appendData:[parameterStr dataUsingEncoding:NSUTF8StringEncoding]];

六. 簡單封裝

1. 將文件名和文件地址纱皆、參數(shù)key值和參數(shù)具體值分別封裝為字典

  • 設(shè)置文件字典
    // 設(shè)置上傳文件在服務(wù)器存儲的名稱
    NSString *name1 = @"photo.jpg";
    NSString *name2 = @"math.h";
    NSString *name3 = @"video.json";

    // 設(shè)置文件地址
    NSString *filePath1 = @"/Users/wangpengfei/Desktop/IMG_5097.jpg";
    NSString *filePath2 = @"/Users/wangpengfei/Desktop/Math.m";
    NSString *filePath3 = @"/Users/wangpengfei/Desktop/vedios.json";

    NSDictionary *fileDict = @{
                               name1:filePath1,
                               name2:filePath2,
                               name3:filePath3
                               };
  • 設(shè)置普通文本參數(shù)字典
    NSDictionary *parameters = @{
                                 @"username":@"wpf",
                                 @"password":@"12300",
                                 @"age":@"24"
                                 };

2. 方法的封裝

  • 方法名
    - (NSData *)getHttpBodyWithFileKey:(NSString *)fileKey fileDict:(NSDictionary *)fileDict parameters:(NSDictionary *)parameters
  • 遍歷文件字典
    // 遍歷文件參數(shù)字典拇惋,取出文件字典中的 key值 和 value 值
    [fileDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {

        // 上傳文件在服務(wù)器中保存的名稱
        NSString *fileName = key;
        // 上傳文件在本地的路徑
        NSString *filePath = obj;

        // 上傳文件的請求體格式
        // 1. 文件的上邊界
        // 1.1 獲取文件上邊界的字符串
        NSMutableString *headerStrM1 = [NSMutableString stringWithFormat:@"\r\n--%@\r\n", kBoundary];

        [headerStrM1 appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n", fileKey, fileName];

        [headerStrM1 appendFormat:@"Content-Type: %@\r\n\r\n", @"application/octet-stream"];

        // 1.2 將字符串轉(zhuǎn)為二進(jìn)制數(shù)據(jù),并添加到請求體中
        [data appendData:[headerStrM1 dataUsingEncoding:NSUTF8StringEncoding]];

        // 2. 獲取文件的二進(jìn)制數(shù)據(jù)抹剩,并添加到請求體中
        [data appendData:[NSData dataWithContentsOfFile:filePath]];
    }];
  • 遍歷普通文本參數(shù)字典
    [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        //  參數(shù)格式:
        //    -----------------------------16778832101575341713442286528
        //    Content-Disposition: form-data; name="username"
        //
        //    Wpf

        NSString *parameterKey = key;
        NSString *parameterValue = obj;

        // 1. 普通參數(shù)的上邊界
        NSMutableString *parameterStr = [NSMutableString stringWithFormat:@"\r\n--%@\r\n", kBoundary];
        // name=%@ :服務(wù)器接收普通文本參數(shù)的key值.后端人員告訴我們.
        // 文本參數(shù)也有可能有多個...
        [parameterStr appendFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n", parameterKey];

        // 2. 第一個普通參數(shù)的內(nèi)容
        [parameterStr appendString:parameterValue];

        [data appendData:[parameterStr dataUsingEncoding:NSUTF8StringEncoding]];
    }];

如果在 iOS 中,要實(shí)現(xiàn)POST上傳文件,需要按照上述格式,拼接數(shù)據(jù)!

因?yàn)?格式是 W3C 指定的標(biāo)準(zhǔn)格式,蘋果沒有做任何封裝!其他語言,都做了封裝!

3. 方法的調(diào)用

  • 設(shè)置請求體
    request.HTTPBody = [self getHttpBodyWithFileKey:@"userfile[]" fileDict:fileDict parameters:parameters];

七. POST多文件上傳方法的封裝

  • 基本參數(shù)
  • urlString:網(wǎng)絡(luò)接口
  • fileKey:服務(wù)器接收用戶上傳文件的key值
  • fileDict:文件字典
  • parameters:普通文本參數(shù)的字典
  • success:上傳成功時調(diào)用的block
  • fail:上傳失敗時調(diào)用的block
  • 方法名
    - (void)POSTMoreFileWithUrlString:(NSString *)urlString
     fileKey:(NSString *)fileKey fileDict:(NSDictionary *)fileDict
     parameters:(NSDictionary *)parameters
     success:(successBlock)success fail:(failBlock)fail;
  • 其他改動同POST單文件的深入封裝-上傳封裝

八. AFN-第三方框架的使用

  • AFN 能夠同時實(shí)現(xiàn)上傳一個文件,有些格式的文件,用 AFN 無法上傳!
  • ASI 能夠同時實(shí)現(xiàn)上傳多個文件,MRC的,2012年就停止更新了,設(shè)計(jì)的目標(biāo)平臺, iOS 2.0/iOS 3.0 !

1. 上傳文件

    // 1. 創(chuàng)建管理者
    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];

    // 2. 發(fā)送請求
    [mgr POST:@"http://localhost/upload/upload.php" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        // formData :設(shè)置上傳文件所需要的參數(shù),兩種上傳方法:
        // <1> 通過本地文件的 url 上傳
        {
            NSString *fromFile = @"/Users/wangpengfei/Desktop/meinv.jpg";

            NSURL *url = [NSURL URLWithString:@"file:///Users/wangpengfei/Desktop/IMG_5544.jpg"];
            // url :需要上傳文件的文件路徑
            // name :服務(wù)器接收的文件名.
            // fileName: 文件在服務(wù)器中保存的名字
            // mimeType : 文件類型
            [formData appendPartWithFileURL:url name:@"userfile" fileName:@"beauty.jpg" mimeType:@"image/jpg" error:NULL];
        }
        // <2> 通過文件的 二進(jìn)制數(shù)據(jù) 上傳
        {
            NSData *data = [NSData dataWithContentsOfFile:zipFile];

            [formData appendPartWithFileData:data name:@"userfile" fileName:@"beauty.zip" mimeType:@"gzip"];
        }

        } success:^(AFHTTPRequestOperation *operation, id responseObject) {
            // 上傳成功之后的回調(diào)
            NSLog(@"%@",responseObject);

        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            //  上傳失敗之后的回調(diào)
            NSLog(@"error-->%@", error);
    }];

2. 監(jiān)測網(wǎng)絡(luò)狀態(tài)

    // 創(chuàng)建 網(wǎng)絡(luò)狀態(tài)管理者
    AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];

    // 監(jiān)測網(wǎng)絡(luò)狀態(tài)的改變
    [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        // 當(dāng)網(wǎng)絡(luò)狀態(tài)發(fā)生改變的時候調(diào)用這個block
        switch (status) {
            case AFNetworkReachabilityStatusReachableViaWiFi:
            NSLog(@"WIFI網(wǎng)絡(luò)");
            break;

            case AFNetworkReachabilityStatusReachableViaWWAN:
            NSLog(@"蜂窩網(wǎng)絡(luò)");
            break;

            case AFNetworkReachabilityStatusNotReachable:
            NSLog(@"沒有網(wǎng)絡(luò)");
            break;

            case AFNetworkReachabilityStatusUnknown:
            NSLog(@"未知網(wǎng)絡(luò)");
            break;
            default:
                break;
        }
    }];

    // 開始監(jiān)控
    [mgr startMonitoring];

3. Reachability 監(jiān)測網(wǎng)絡(luò)狀態(tài)(第三方框架)

  • 注冊通知觀察者,網(wǎng)絡(luò)狀態(tài)改變時,接收通知!
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(InternetStatusChanged) name:kReachabilityChangedNotification object:nil];

    // 控制器銷毀時,移除通知觀察者.
    -(void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
  • 根據(jù)當(dāng)前網(wǎng)絡(luò)狀態(tài),做出不同的響應(yīng).
    - (void)InternetStatusChanged
    {
        NSLog(@"網(wǎng)絡(luò)狀態(tài)改變了");

        if ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == ReachableViaWiFi) {
            NSLog(@"Wifi 網(wǎng)絡(luò)");
        }
        if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus == ReachableViaWWAN) {
            NSLog(@"蜂窩移動網(wǎng)絡(luò)");
        }
        if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus == NotReachable)
        {
            NSLog(@"沒有網(wǎng)絡(luò)");
        }
    }
  • 創(chuàng)建 Reachability 對象,開始監(jiān)測網(wǎng)絡(luò)狀態(tài)的改變
    - (void)MonitorInternetStatus
    {
        Reachability *reachability = [Reachability reachabilityForInternetConnection];

        [reachability startNotifier];

        self.reachability = reachability;
    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [self MonitorInternetStatus];
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撑帖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子澳眷,更是在濱河造成了極大的恐慌胡嘿,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钳踊,死亡現(xiàn)場離奇詭異衷敌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拓瞪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門缴罗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祭埂,你說我怎么就攤上這事面氓。” “怎么了蛆橡?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵舌界,是天一觀的道長。 經(jīng)常有香客問我泰演,道長呻拌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任睦焕,我火速辦了婚禮藐握,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘垃喊。我一直安慰自己猾普,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布缔御。 她就那樣靜靜地躺著抬闷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笤成,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天评架,我揣著相機(jī)與錄音,去河邊找鬼炕泳。 笑死纵诞,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的培遵。 我是一名探鬼主播浙芙,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼籽腕!你這毒婦竟也來了嗡呼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤皇耗,失蹤者是張志新(化名)和其女友劉穎南窗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體郎楼,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡万伤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了呜袁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敌买。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖阶界,靈堂內(nèi)的尸體忽然破棺而出虹钮,到底是詐尸還是另有隱情,我是刑警寧澤荐操,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布芜抒,位于F島的核電站珍策,受9級特大地震影響托启,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攘宙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一屯耸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蹭劈,春花似錦疗绣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春塔逃,著一層夾襖步出監(jiān)牢的瞬間讯壶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工湾盗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伏蚊,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓格粪,卻偏偏與公主長得像躏吊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子帐萎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容