多線程網(wǎng)絡-7

Xmind

多線程和網(wǎng)絡7.jpg

②發(fā)送POST請求上傳文件

/*文件上傳相關的代碼如下*/
-(void)upload
{
    //1.創(chuàng)建一個請求管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //2.發(fā)送POST請求上傳數(shù)據(jù)
    /*
     第一個參數(shù):請求路徑:NSString類型
     第二個參數(shù):要上傳的非文件參數(shù)
     第三個參數(shù):block回調
        在該回調中,需要利用formData拼接即將上傳的二進制數(shù)據(jù)
     第三個參數(shù):上傳成功的block回調
        task:dataTask(任務)
        responseObject:服務器返回的數(shù)據(jù)
     第四個參數(shù):上傳失敗的block回調
        error:錯誤信息象迎,如果上傳文件失敗刹衫,那么error里面包含了錯誤的描述信息
     */

    NSDictionary *dict = @{
                           @"username":@"wenidngding"
                           };

    [manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

        //把本地的圖片轉換為NSData類型的數(shù)據(jù)
        UIImage *image = [UIImage imageNamed:@"123"];
        NSData *data = UIImagePNGRepresentation(image);

        /*
         //拼接二進制文件數(shù)據(jù)
         第一個參數(shù):要上傳的文件的二進制數(shù)據(jù)
         第二個參數(shù):服務器接口規(guī)定的名稱
         第三個參數(shù):這個參數(shù)上傳到服務器之后用什么名字來進行保存
         第四個參數(shù):上傳文件的MIMEType類型
         */
        [formData appendPartWithFileData:data name:@"file" fileName:@"xxoo.png" mimeType:@"application/octet-stream"];

    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        NSLog(@"請求成功---%@",responseObject);

    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"請求失敗--%@",error);
    }];
}

-(void)upload2
{
    NSLog(@"%s",__func__);

    //1.創(chuàng)建一個請求管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //2.發(fā)送POST請求上傳數(shù)據(jù)
    /*
     第一個參數(shù):請求路徑:NSString類型
     第二個參數(shù):要上傳的非文件參數(shù)
     第三個參數(shù):block回調
     在該回調中判莉,需要利用formData拼接即將上傳的二進制數(shù)據(jù)
     第三個參數(shù):上傳成功的block回調
     task:dataTask(任務)
     responseObject:服務器返回的數(shù)據(jù)
     第四個參數(shù):上傳失敗的block回調
     error:錯誤信息脾歧,如果上傳文件失敗讨便,那么error里面包含了錯誤的描述信息
     */

    NSDictionary *dict = @{
                           @"username":@"wenidngding"
                           };

    [manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

        //本地文件的url
        NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/文頂頂/Desktop/KF[WTI`AQ3T`A@3R(B96D89.gif"];
        /*
         //拼接二進制文件數(shù)據(jù)
         第一個參數(shù):要上傳文件的url路徑
         第二個參數(shù):服務器要求的參數(shù)名稱
         第三個參數(shù):這個文件上傳到服務器之后叫什么名稱
         第四個參數(shù):文件的mimetype類型
         第五個參數(shù):錯誤信息
         */
//        [formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"xx.png" mimeType:@"application/octet-stream" error:nil];

        //另外一種上傳文件的方式
        /*
         說明:該方法和上面的方法等價充甚,不過該方法更加簡單其內部會自動的的根據(jù)url路徑確定文件保存名稱,并通過內部方法獲取上傳文件的mimetype類型
         */
        [formData appendPartWithFileURL:fileUrl name:@"file" error:nil];


    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        NSLog(@"請求成功---%@",responseObject);

    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"請求失敗--%@",error);
    }];
}

在控制器中通過該工具類來發(fā)送請求

+ (instancetype)shareNetworkTools{
    static XMGNetworkTools *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 注意: BaseURL中一定要以/結尾
        instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://120.25.226.186:32812/"]];
    });
    return instance;
}

⑤還有一種情況就是霸褒,服務器返回給我的數(shù)據(jù)確實是json,但是我使用json來解析的時候報錯

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    /*01 設置AFN采用什么樣的方式來解析服務器返回的數(shù)據(jù)*/
    //告訴AFN津坑,響應的時候使用XML的方式解析
    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
    //采用二進制的方式來解析數(shù)據(jù)
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    //采用JSON的方式來解析數(shù)據(jù)
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];


    /*02 告訴AFN,再序列化服務器返回的數(shù)據(jù)的時候傲霸,支持此種類型
    [AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"text/xml"];

    NSDictionary *dict = @{
                           @"username":@"223",
                           @"pwd":@"ewr",
                           @"type":@"XML"
                           };

    [manager GET:@"http://120.25.226.186:32812/login" parameters:dict success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        NSLog(@"%@",[responseObject class]);
    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"%@",error);
    }];
}

AFN監(jiān)測

-(void)AFNReachability
{
    //1.創(chuàng)建網(wǎng)絡監(jiān)聽管理者
    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];

    //2.監(jiān)聽網(wǎng)絡狀態(tài)的改變
    /*
     AFNetworkReachabilityStatusUnknown          = 未知
     AFNetworkReachabilityStatusNotReachable     = 沒有網(wǎng)絡
     AFNetworkReachabilityStatusReachableViaWWAN = 3G
     AFNetworkReachabilityStatusReachableViaWiFi = WIFI
     */
    [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        switch (status) {
            case AFNetworkReachabilityStatusUnknown:
                NSLog(@"未知");
                break;
            case AFNetworkReachabilityStatusNotReachable:
                NSLog(@"沒有網(wǎng)絡");
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                NSLog(@"3G");
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                NSLog(@"WIFI");
                break;

            default:
                break;
        }
    }];

    //3.開始監(jiān)聽
    [manager startMonitoring];
}

蘋果原生Reachability監(jiān)測

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1.注冊一個通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChange) name:kReachabilityChangedNotification object:nil];

    //2.拿到一個對象疆瑰,然后調用開始監(jiān)聽方法
    Reachability *r = [Reachability reachabilityForInternetConnection];
    [r startNotifier];

    //持有該對象眉反,不要讓該對象釋放掉
    self.r = r;

}

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


-(void)networkChange
{
    //獲取當前網(wǎng)絡的狀態(tài)
    if([Reachability reachabilityForLocalWiFi].currentReachabilityStatus != NotReachable)
    {
        NSLog(@"當前網(wǎng)絡為WIFI");
    }else if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus != NotReachable)
    {
        NSLog(@"當前網(wǎng)絡為手機自帶網(wǎng)絡");
    }else
    {
        NSLog(@"當前沒有網(wǎng)絡");
    }
}

NSURLSession發(fā)送HTTPS請求,則需要重寫didReceiveChallenge代理方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSURLSessionDataTask *task =  [session dataTaskWithURL:[NSURL URLWithString:@"https://www.apple.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    [task resume];
}

/*
 只要請求的地址是HTTPS的, 就會調用這個代理方法
 我們需要在該方法中告訴系統(tǒng), 是否信任服務器返回的證書
 Challenge: 挑戰(zhàn) 質問 (包含了受保護的區(qū)域)
 protectionSpace : 受保護區(qū)域
 NSURLAuthenticationMethodServerTrust : 證書的類型是 服務器信任
 */
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
    //    NSLog(@"didReceiveChallenge %@", challenge.protectionSpace);
    NSLog(@"調用了最外層");
    // 1.判斷服務器返回的證書類型, 是否是服務器信任
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSLog(@"調用了里面這一層是服務器信任的證書");
        /*
         NSURLSessionAuthChallengeUseCredential = 0,                     使用證書
         NSURLSessionAuthChallengePerformDefaultHandling = 1,            忽略證書(默認的處理方式)
         NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,     忽略書證, 并取消這次請求
         NSURLSessionAuthChallengeRejectProtectionSpace = 3,            拒絕, 下一次再詢問
         */
//        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

        NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
         NSURLCredential *credential = challenge.proposedCredential;
    //如何處理這個證書+安全證書(要接受的證書)
        completionHandler(NSURLSessionAuthChallengeUseCredential , card);
    }
}

如何安裝

1.先升級Gem
    sudo gem update --system
2.切換cocoapods的數(shù)據(jù)源
    【先刪除穆役,再添加寸五,查看】
    gem sources --remove https://rubygems.org/
    gem sources -a https://ruby.taobao.org/
    gem sources -l
3.安裝cocoapods
    sudo gem install cocoapods
4.將Podspec文件托管地址從github切換到國內的oschina
    【先刪除,再添加耿币,再更新】
    pod repo remove master
    pod repo add master http://git.oschina.net/akuandev/Specs.git
    pod repo add master https://gitcafe.com/akuandev/Specs.git
    pod repo update
5.設置pod倉庫
    pod setup
6.測試
    【如果有版本號梳杏,則說明已經(jīng)安裝成功】
    pod --version
7.利用cocoapods來安裝第三方框架
    01 進入要安裝框架的項目的.xcodeproj同級文件夾
    02 在該文件夾中新建一個文件podfile
    03 在文件中告訴cocoapods需要安裝的框架信息
        a.該框架支持的平臺
        b.適用的iOS版本
        c.框架的名稱
        d.框架的版本
8.安裝
pod install --no-repo-update
pod update --no-repo-update

PPT

數(shù)據(jù)安全

Snip20170409_20.png
Snip20170409_21.png
Snip20170409_22.png
Snip20170409_23.png
Snip20170409_24.png
Snip20170409_25.png
Snip20170409_26.png
Snip20170409_27.png
Snip20170409_28.png
Snip20170409_29.png
Snip20170409_30.png
Snip20170409_31.png
Snip20170409_32.png
Snip20170409_33.png
Snip20170409_34.png
Snip20170409_35.png
Snip20170409_36.png

AFN

Snip20170409_37.png
Snip20170409_38.png
Snip20170409_39.png
Snip20170410_42.png
Snip20170410_43.png
Snip20170409_40.png
Snip20170409_41.png

配圖

Snip20160227_4.png
Snip20160227_5.png
Snip20160227_6.png
Snip20160227_7.png
Snip20160227_8.png
Snip20160227_9.png

CocoaPods

CocoaPods.jpg
CocoaPods2.jpg
CocoaPods3.jpg

GitBook

0.AFN

AFNetworking是一款在OS X和iOS下都令人喜愛的網(wǎng)絡庫。為了迎合iOS新版本的升級, AFNetworking在3.0版本中刪除了基于 NSURLConnection API的所有支持淹接。如果你的項目以前使用過這些API十性,建議您立即升級到基于 NSURLSession 的API的AFNetworking的版本。本指南將引導您完成這個過程塑悼。

本指南是為了引導使用AFNetworking 2.x升級到最新的版本API劲适,以達到過渡的目的,并且解釋了新增和更改的設計結構厢蒜。

新設備要求: iOS 7, Mac OS X 10.9, watchOS 2, tvOS 9, & Xcode 7

AFNetworking 3.0正式支持的iOS 7霞势, Mac OS X的10.9, watchOS 2 斑鸦, tvOS 9 和Xcode 7愕贡。如果你想使用AFNetworking在針對較舊版本的SDK項目,請檢查README的兼容性信息巷屿。

NSURLConnection的API已廢棄

AFNetworking 1.0建立在NSURLConnection的基礎API之上 固以,AFNetworking 2.0開始使用NSURLConnection的基礎API ,以及較新基于NSURLSession的API的選項嘱巾。 AFNetworking 3.0現(xiàn)已完全基于NSURLSession的API嘴纺,這降低了維護的負擔,同時支持蘋果增強關于NSURLSession提供的任何額外功能浓冒。由于Xcode 7中栽渴,NSURLConnection的API已經(jīng)正式被蘋果棄用。雖然該API將繼續(xù)運行稳懒,但將沒有新功能將被添加闲擦,并且蘋果已經(jīng)通知所有基于網(wǎng)絡的功能,以充分使NSURLSession向前發(fā)展场梆。

AFNetworking 2.X將繼續(xù)獲得關鍵的隱患和安全補丁墅冷,但沒有新的功能將被添加。Alamofire(Swift下的網(wǎng)絡請求)軟件基金會建議或油,所有的項目遷移到基于NSURLSession的API寞忿。

棄用的類

下面的類已從AFNetworking 3.0中廢棄:

AFURLConnectionOperation
AFHTTPRequestOperation
AFHTTPRequestOperationManager
修改的類

下面的類包含基于NSURLConnection的API的內部實現(xiàn)。他們已經(jīng)被使用NSURLSession重構:

UIImageView+AFNetworking
UIWebView+AFNetworking
UIButton+AFNetworking
遷移

AFHTTPRequestOperationManager 核心代碼

如果你以前使用 AFHTTPRequestOperationManager 顶岸, 你將需要遷移去使用 AFHTTPSessionManager腔彰。 以下的類在兩者過渡間并沒有變化:

securityPolicy
requestSerializer
responseSerializer
接下來舉一個關于AFHTTPSessionManager的簡單例子叫编。注意HTTP網(wǎng)絡請求返回的不再是AFHTTPRequestOperation, 修改成為了NSURLSessionTask,并且成功和失敗的Block塊中的參數(shù)也變更為了NSURLSessionTask霹抛,而不再是AFHTTPRequestOperation搓逾。

AFNetworking 2.x

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"請求的url" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"成功");
} failure:^(AFHTTPRequestOperation *operation, NSError*error) {
        NSLog(@"失敗");
}];
AFNetworking 3.0

AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
[session GET:@"請求的url" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"成功");
} failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"失敗");
}];
AFHTTPRequestOperation 核心代碼

與NSURLConnection對象不同,每個共享應用范圍的設置如會話管理杯拐、緩存策略霞篡、Cookie存儲以及URL協(xié)議等,這些NSURLSession對象都可以單獨進行配置端逼。使用特定的配置來初始化會話朗兵,它可以發(fā)送任務來獲取數(shù)據(jù),并上傳或下載文件顶滩。

在AFNetworking 2.0中余掖,使用AFHTTPRequestOperation,有可能創(chuàng)建一個沒有額外開銷的獨立的網(wǎng)絡請求來獲取數(shù)據(jù)诲祸。NSURLSession則需要更多的開銷浊吏,為了獲得所要請求的數(shù)據(jù)而昨。

接下來救氯,將要通過AFHTTPSessionManager創(chuàng)建一個單例,并創(chuàng)建一個任務和啟動它歌憨。

AFNetworking 2.x

NSURL *URL = [NSURL URLWithString:@""];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
}];
[[NSOperationQueue mainQueue] addOperation:op];
AFNetworking 3.0

NSURL *URL = [NSURL URLWithString:@""];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:URL.absoluteString parameters:nil success:^(NSURLSessionTask *task, id responseObject) {
        NSLog(@"JSON: %@", responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
        NSLog(@"Error: %@", error);
}];
UIKit的遷移

圖片下載已經(jīng)被重構着憨,以遵循AlamofireImage架構與新的AFImageDownloader類。這個類的圖片下載職責的代理人是UIButton與UIImageView的類目务嫡,并且提供了一些方法甲抖,在必要時可以自定義。類別中心铃,下載遠程圖片的實際方法沒有改變准谚。

UIWebView的類目被重構為使用AFHTTPSessionManager作為其網(wǎng)絡請求。

UIAlertView的類目被廢棄

從AFNetworking 3.0后UIAlertView的類目因過時而被廢棄去扣。并沒有提供UIAlertController類目的計劃柱衔,因為這是應用程序應處理的邏輯,而不是這個庫愉棱。

1.AFN框架基本使用

  • 0.1 AFN內部結構
AFN結構體
    - NSURLConnection
        + AFURLConnectionOperation(已經(jīng)被廢棄)
        + AFHTTPRequestOperation(已經(jīng)被廢棄)
        + AFHTTPRequestOperationManager(封裝了常用的 HTTP 方法)(已經(jīng)被廢棄)
            * 屬性
                * baseURL :AFN建議開發(fā)者針對 AFHTTPRequestOperationManager 自定義個一個單例子類唆铐,設置 baseURL, 所有的網(wǎng)絡訪問,都只使用相對路徑即可
                * requestSerializer :請求數(shù)據(jù)格式/默認是二進制的 HTTP
                * responseSerializer :響應的數(shù)據(jù)格式/默認是 JSON 格式
                * operationQueue
                * reachabilityManager :網(wǎng)絡連接管理器
            * 方法
                * manager :方便創(chuàng)建管理器的類方法
                * HTTPRequestOperationWithRequest :在訪問服務器時奔滑,如果要告訴服務器一些附加信息艾岂,都需要在 Request 中設置
                * GET
                * POST

    - NSURLSession
        + AFURLSessionManager
        + AFHTTPSessionManager(封裝了常用的 HTTP 方法)
            * GET
            * POST
            * UIKit + AFNetworking 分類
            * NSProgress :利用KVO

    - 半自動的序列化&反序列化的功能
        + AFURLRequestSerialization :請求的數(shù)據(jù)格式/默認是二進制的
        + AFURLResponseSerialization :響應的數(shù)據(jù)格式/默認是JSON格式
    - 附加功能
        + 安全策略
            * HTTPS
            * AFSecurityPolicy
        + 網(wǎng)絡檢測
            * 對蘋果的網(wǎng)絡連接檢測做了一個封裝
            * AFNetworkReachabilityManager

建議:
可以學習下AFN對 UIKit 做了一些分類, 對自己能力提升是非常有幫助的
  • 0.2 AFN的基本使用

(1)發(fā)送POST請求的方式

-(void)post
{
    //1.創(chuàng)建會話管理者
    //AFHTTPSessionManager內部是基于NSURLSession實現(xiàn)的
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //2.創(chuàng)建參數(shù)
    NSDictionary *dict = @{
                           @"username":@"520it",
                           @"pwd":@"520it",
                           };

    //3.發(fā)送POST請求
    /*
     http://120.25.226.186:32812/login?username=ee&pwd=ee&type=JSON
     第一個參數(shù):NSString類型的請求路徑,AFN內部會自動將該路徑包裝為一個url并創(chuàng)建請求對象
     第二個參數(shù):請求參數(shù)朋其,以字典的方式傳遞王浴,AFN內部會判斷當前是POST請求還是GET請求脆炎,以選擇直接拼接還是轉換為NSData放到請求體中傳遞
     第三個參數(shù):進度回調 此處為nil
     第四個參數(shù):請求成功之后回調Block
     第五個參數(shù):請求失敗回調Block
     */
    [manager POST:@"http://120.25.226.186:32812/login" parameters:dict progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        //注意:responseObject:請求成功返回的響應結果(AFN內部已經(jīng)把響應體轉換為OC對象,通常是字典或數(shù)組)
        NSLog(@"請求成功---%@",responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"請求失敗---%@",error);
    }];
}

(2)使用AFN下載文件

-(void)download
{
    //1.創(chuàng)建會話管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];


    //2.創(chuàng)建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_13.png"]];

    //3.創(chuàng)建下載Task
    /*
     第一個參數(shù):請求對象
     第二個參數(shù):進度回調
        downloadProgress.completedUnitCount :已經(jīng)下載的數(shù)據(jù)
        downloadProgress.totalUnitCount:數(shù)據(jù)的總大小
     第三個參數(shù):destination回調叼耙,該block需要返回值(NSURL類型)腕窥,告訴系統(tǒng)應該把文件剪切到什么地方
        targetPath:文件的臨時保存路徑
        response:響應頭信息
     第四個參數(shù):completionHandler請求完成后回調
        response:響應頭信息
        filePath:文件的保存路徑,即destination回調的返回值
        error:錯誤信息
     */
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        NSLog(@"%f",1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);

    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
        NSLog(@"%@\n%@",targetPath,fullPath);
        return [NSURL fileURLWithPath:fullPath];

    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        NSLog(@"%@",filePath);
    }];

    //4.執(zhí)行Task
    [downloadTask resume];
}

1.AFN使用技巧

1.在開發(fā)的時候可以創(chuàng)建一個工具類筛婉,繼承自我們的AFN中的請求管理者簇爆,再控制器中真正發(fā)請求的代碼使用自己封裝的工具類。
2.這樣做的優(yōu)點是以后如果修改了底層依賴的框架爽撒,那么我們修改這個工具類就可以了入蛆,而不用再一個一個的去修改。
3.該工具類一般提供一個單例方法硕勿,在該方法中會設置一個基本的請求路徑哨毁。
4.該方法通常還會提供對GET或POST請求的封裝。
5.在外面的時候通過該工具類來發(fā)送請求
6.單例方法:
+ (instancetype)shareNetworkTools
{
    static XMGNetworkTools *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 注意: BaseURL中一定要以/結尾
        instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://120.25.226.186:32812/"]];
    });
    return instance;
}

2.AFN文件上傳

1.文件上傳拼接數(shù)據(jù)的第一種方式
[formData appendPartWithFileData:data name:@"file" fileName:@"xxoo.png" mimeType:@"application/octet-stream"];
2.文件上傳拼接數(shù)據(jù)的第二種方式
 [formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"xx.png" mimeType:@"application/octet-stream" error:nil];
3.文件上傳拼接數(shù)據(jù)的第三種方式
 [formData appendPartWithFileURL:fileUrl name:@"file" error:nil];
4.【注】在資料中已經(jīng)提供了一個用于文件上傳的分類源武。

/*文件上傳相關的代碼如下*/
-(void)upload1
{
    //1.創(chuàng)建會話管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //2.處理參數(shù)(非文件參數(shù))
    NSDictionary *dict = @{
                           @"username":@"123"
                           };

    //3.發(fā)送請求上傳文件
    /*
     第一個參數(shù):請求路徑(NSString類型)
     第二個參數(shù):非文件參數(shù)扼褪,以字典的方式傳遞
     第三個參數(shù):constructingBodyWithBlock 在該回調中拼接文件參數(shù)
     第四個參數(shù):progress 進度回調
        uploadProgress.completedUnitCount:已經(jīng)上傳的數(shù)據(jù)大小
        uploadProgress.totalUnitCount:數(shù)據(jù)的總大小
     第五個參數(shù):success 請求成功的回調
        task:上傳Task
        responseObject:服務器返回的響應體信息(已經(jīng)以JSON的方式轉換為OC對象)
     第六個參數(shù):failure 請求失敗的回調
        task:上傳Task
        error:錯誤信息
     */
    [manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

        UIImage *image = [UIImage imageNamed:@"Snip20160117_1"];
        NSData *imageData = UIImagePNGRepresentation(image);

        //在該block中拼接要上傳的文件參數(shù)
        /*
         第一個參數(shù):要上傳的文件二進制數(shù)據(jù)
         第二個參數(shù):文件參數(shù)對應的參數(shù)名稱,此處為file是該臺服務器規(guī)定的(通常會在接口文檔中提供)
         第三個參數(shù):該文件上傳到服務后以什么名稱保存
         第四個參數(shù):該文件的MIMeType類型
         */
        [formData appendPartWithFileData:imageData name:@"file" fileName:@"123.png" mimeType:@"image/png"];

    } progress:^(NSProgress * _Nonnull uploadProgress) {
        NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        NSLog(@"請求成功----%@",responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"請求失敗----%@",error);
    }];
}

-(void)upload2
{
    //1.創(chuàng)建會話管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    //2.處理參數(shù)(非文件參數(shù))
    NSDictionary *dict = @{
                           @"username":@"123"
                           };

    //3.發(fā)送請求上傳文件
    /*
     第一個參數(shù):請求路徑(NSString類型)
     第二個參數(shù):非文件參數(shù)粱栖,以字典的方式傳遞
     第三個參數(shù):constructingBodyWithBlock 在該回調中拼接文件參數(shù)
     第四個參數(shù):progress 進度回調
        uploadProgress.completedUnitCount:已經(jīng)上傳的數(shù)據(jù)大小
        uploadProgress.totalUnitCount:數(shù)據(jù)的總大小
     第五個參數(shù):success 請求成功的回調
        task:上傳Task
        responseObject:服務器返回的響應體信息(已經(jīng)以JSON的方式轉換為OC對象)
     第六個參數(shù):failure 請求失敗的回調
        task:上傳Task
        error:錯誤信息
     */
    [manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

        NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/文頂頂/Desktop/Snip20160117_1.png"];


        //在該block中拼接要上傳的文件參數(shù)
        //第一種拼接方法
        /*
         第一個參數(shù):要上傳的文件的URL路徑
         第二個參數(shù):文件參數(shù)對應的參數(shù)名稱话浇,此處為file是該臺服務器規(guī)定的(通常會在接口文檔中提供)
         第三個參數(shù):該文件上傳到服務后以什么名稱保存
         第四個參數(shù):該文件的MIMeType類型
         第五個參數(shù):錯誤信息,傳地址
         */
        //[formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"1234.png" mimeType:@"image/png" error:nil];


        //第二種拼接方法:簡寫方法
        /*
         第一個參數(shù):要上傳的文件的URL路徑
         第二個參數(shù):文件參數(shù)對應的參數(shù)名稱闹究,此處為file
         第三個參數(shù):錯誤信息
         說明:AFN內部自動獲得路徑URL地址的最后一個節(jié)點作為文件的名稱幔崖,內部調用C語言的API獲得文件的類型
         */
        [formData appendPartWithFileURL:fileUrl name:@"file" error:nil];

    } progress:^(NSProgress * _Nonnull uploadProgress) {
        NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        NSLog(@"請求成功----%@",responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        NSLog(@"請求失敗----%@",error);
    }];
}

3.使用AFN進行序列化處理

/*
1.AFN它內部默認把服務器響應的數(shù)據(jù)當做json來進行解析,所以如果服務器返回給我的不是JSON數(shù)據(jù)那么請求報錯渣淤,這個時候需要設置AFN對響應信息的解析方式赏寇。AFN提供了三種解析響應信息的方式,分別是:
1)AFXMLParserResponseSerializer----XML
2) AFHTTPResponseSerializer---------默認二進制響應數(shù)據(jù)
3)AFJSONResponseSerializer---------JSON

2.還有一種情況就是服務器返回給我們的數(shù)據(jù)格式不太一致(開發(fā)者工具Content-Type:text/xml),那么這種情況也有可能請求不成功价认。解決方法:
1) 直接在源代碼中修改嗅定,添加相應的Content-Type
2) 拿到這個屬性,添加到它的集合中

3.相關代碼
-(void)srializer
{
    //1.創(chuàng)建請求管理者用踩,內部基于NSURLSession
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    /* 知識點1:設置AFN采用什么樣的方式來解析服務器返回的數(shù)據(jù)*/

    //如果返回的是XML渠退,那么告訴AFN,響應的時候使用XML的方式解析
    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

    //如果返回的就是二進制數(shù)據(jù)捶箱,那么采用默認二進制的方式來解析數(shù)據(jù)
    //manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    //采用JSON的方式來解析數(shù)據(jù)
    //manager.responseSerializer = [AFJSONResponseSerializer serializer];


    /*知識點2 告訴AFN智什,再序列化服務器返回的數(shù)據(jù)的時候,支持此種類型
    [AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"text/xml"];

    //2.把所有的請求參數(shù)通過字典的方式來裝載丁屎,GET方法內部會自動把所有的鍵值對取出以&符號拼接并最后用荠锭?符號連接在請求路徑后面
    NSDictionary *dict = @{
                           @"username":@"223",
                           @"pwd":@"ewr",
                           @"type":@"XML"
                           };

    //3.發(fā)送GET請求
    [manager GET:@"http://120.25.226.186:32812/login" parameters:dict success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

        //4.請求成功的回調block
        NSLog(@"%@",[responseObject class]);
    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {

        //5.請求失敗的回調,可以打印error的值查看錯誤信息
        NSLog(@"%@",error);
    }];
}

4.使用AFN來檢測網(wǎng)絡狀態(tài)

/*
說明:可以使用AFN框架中的AFNetworkReachabilityManager來監(jiān)聽網(wǎng)絡狀態(tài)的改變晨川,也可以利用蘋果提供的Reachability來監(jiān)聽证九。建議在開發(fā)中直接使用AFN框架處理删豺。
 */
//使用AFN框架來檢測網(wǎng)絡狀態(tài)的改變
-(void)AFNReachability
{
    //1.創(chuàng)建網(wǎng)絡監(jiān)聽管理者
    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];

    //2.監(jiān)聽網(wǎng)絡狀態(tài)的改變
    /*
     AFNetworkReachabilityStatusUnknown          = 未知
     AFNetworkReachabilityStatusNotReachable     = 沒有網(wǎng)絡
     AFNetworkReachabilityStatusReachableViaWWAN = 3G
     AFNetworkReachabilityStatusReachableViaWiFi = WIFI
     */
    [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        switch (status) {
            case AFNetworkReachabilityStatusUnknown:
                NSLog(@"未知");
                break;
            case AFNetworkReachabilityStatusNotReachable:
                NSLog(@"沒有網(wǎng)絡");
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                NSLog(@"3G");
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                NSLog(@"WIFI");
                break;

            default:
                break;
        }
    }];

    //3.開始監(jiān)聽
    [manager startMonitoring];
}

------------------------------------------------------------
//使用蘋果提供的Reachability來檢測網(wǎng)絡狀態(tài),如果要持續(xù)監(jiān)聽網(wǎng)絡狀態(tài)的概念愧怜,需要結合通知一起使用呀页。
//提供下載地址:https://developer.apple.com/library/ios/samplecode/Reachability/Reachability.zip

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1.注冊一個通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChange) name:kReachabilityChangedNotification object:nil];

    //2.拿到一個對象,然后調用開始監(jiān)聽方法
    Reachability *r = [Reachability reachabilityForInternetConnection];
    [r startNotifier];

    //持有該對象拥坛,不要讓該對象釋放掉
    self.r = r;
}

//當控制器釋放的時候蓬蝶,移除通知的監(jiān)聽
-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void)networkChange
{
    //獲取當前網(wǎng)絡的狀態(tài)
   if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus == ReachableViaWWAN)
    {
        NSLog(@"當前網(wǎng)絡狀態(tài)為3G");
        return;
    }

    if ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == ReachableViaWiFi)
    {
        NSLog(@"當前網(wǎng)絡狀態(tài)為wifi");
        return;
    }

    NSLog(@"當前沒有網(wǎng)絡");
}

5.數(shù)據(jù)安全

01 攻城利器:Charles(公司中一般都使用該工具來抓包,并做網(wǎng)絡測試)
注意:Charles在使用中的亂碼問題猜惋,可以顯示包內容丸氛,然后打開info.plist文件,找到java目錄下面的VMOptions著摔,在后面添加一項:-Dfile.encoding=UTF-8
02 MD5消息摘要算法是不可逆的缓窜。
03 數(shù)據(jù)加密的方式和規(guī)范一般公司會有具體的規(guī)定,不必多花時間谍咆。

6.HTTPS的基本使用

1.https簡單說明
    HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer)禾锤,是以安全為目標的HTTP通道,簡單講是HTTP的安全版摹察。
    即HTTP下加入SSL層恩掷,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL港粱。 它是一個URI scheme(抽象標識符體系)螃成,句法類同http:體系旦签。用于安全的HTTP數(shù)據(jù)傳輸查坪。
    https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默認端口及一個加密/身份驗證層(在HTTP與TCP之間)宁炫。

2.HTTPS和HTTP的區(qū)別主要為以下四點:
        一偿曙、https協(xié)議需要到ca申請證書,一般免費證書很少羔巢,需要交費望忆。
        二、http是超文本傳輸協(xié)議竿秆,信息是明文傳輸启摄,https 則是具有安全性的ssl加密傳輸協(xié)議。
        三幽钢、http和https使用的是完全不同的連接方式歉备,用的端口也不一樣,前者是80匪燕,后者是443蕾羊。
        四喧笔、http的連接很簡單,是無狀態(tài)的龟再;HTTPS協(xié)議是由SSL+HTTP協(xié)議構建的可進行加密傳輸书闸、身份認證的網(wǎng)絡協(xié)議,比http協(xié)議安全利凑。

3.簡單說明
1)HTTPS的主要思想是在不安全的網(wǎng)絡上創(chuàng)建一安全信道浆劲,并可在使用適當?shù)募用馨头掌髯C書可被驗證且可被信任時,對竊聽和中間人攻擊提供合理的保護哀澈。
2)HTTPS的信任繼承基于預先安裝在瀏覽器中的證書頒發(fā)機構(如VeriSign梳侨、Microsoft等)(意即“我信任證書頒發(fā)機構告訴我應該信任的”)。
3)因此日丹,一個到某網(wǎng)站的HTTPS連接可被信任走哺,如果服務器搭建自己的https 也就是說采用自認證的方式來建立https信道,這樣一般在客戶端是不被信任的哲虾。
4)所以我們一般在瀏覽器訪問一些https站點的時候會有一個提示丙躏,問你是否繼續(xù)。

4.對開發(fā)的影響束凑。
4.1 如果是自己使用NSURLSession來封裝網(wǎng)絡請求晒旅,涉及代碼如下。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSURLSessionDataTask *task =  [session dataTaskWithURL:[NSURL URLWithString:@"https://www.apple.com"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    [task resume];
}

/*
 只要請求的地址是HTTPS的, 就會調用這個代理方法
 我們需要在該方法中告訴系統(tǒng), 是否信任服務器返回的證書
 Challenge: 挑戰(zhàn) 質問 (包含了受保護的區(qū)域)
 protectionSpace : 受保護區(qū)域
 NSURLAuthenticationMethodServerTrust : 證書的類型是 服務器信任
 */
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
    //    NSLog(@"didReceiveChallenge %@", challenge.protectionSpace);
    NSLog(@"調用了最外層");
    // 1.判斷服務器返回的證書類型, 是否是服務器信任
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSLog(@"調用了里面這一層是服務器信任的證書");
        /*
         NSURLSessionAuthChallengeUseCredential = 0,                     使用證書
         NSURLSessionAuthChallengePerformDefaultHandling = 1,            忽略證書(默認的處理方式)
         NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,     忽略書證, 并取消這次請求
         NSURLSessionAuthChallengeRejectProtectionSpace = 3,            拒絕當前這一次, 下一次再詢問
         */
//        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

        NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential , card);
    }
}

4.2 如果是使用AFN框架汪诉,那么我們不需要做任何額外的操作废恋,AFN內部已經(jīng)做了處理。

7 WebView的基本使用

1 概念性知識
    01 webView是有缺點的扒寄,會導致內存泄露鱼鼓,而且這個問題是它系統(tǒng)本身的問題。
    02 手機上面的safai其實就是用webView來實現(xiàn)的
    03 現(xiàn)在的開發(fā)并不完全是原生的開發(fā)该编,而更加傾向于原生+Html5的方式
    04 webView是OC代碼和html代碼之間進行交互的橋梁

2 代碼相關
/*A*網(wǎng)頁操控相關方法**/
    [self.webView goBack];      回退
    [self.webView goForward];   前進
    [self.webView reload];      刷新

    //設置是否能夠前進和回退
    self.goBackBtn.enabled = webView.canGoBack;
    self.fowardBtn.enabled = webView.canGoForward;

/*B*常用的屬性設置**/
    self.webView.scalesPageToFit = YES; 設置網(wǎng)頁自動適應
    self.webView.dataDetectorTypes = UIDataDetectorTypeAll; 設置檢測網(wǎng)頁中的格式類型迄本,all表示檢測所有類型包括超鏈接、電話號碼课竣、地址等嘉赎。
    self.webView.scrollView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);

/*C*相關代理方法**/
    //每當將加載請求的時候調用該方法,返回YES 表示加載該請求于樟,返回NO 表示不加載該請求
    //可以在該方法中攔截請求
    -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    {
        return ![request.URL.absoluteString containsString:@"dushu"];
    }

    //開始加載網(wǎng)頁公条,不僅監(jiān)聽我們指定的請求,還會監(jiān)聽內部發(fā)送的請求
    -(void)webViewDidStartLoad:(UIWebView *)webView

    //網(wǎng)頁加載完畢之后會調用該方法
    -(void)webViewDidFinishLoad:(UIWebView *)webView

    //網(wǎng)頁加載失敗調用該方法
    -(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error

/*D*其它知識點-加載本地資源**/
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"text.html" withExtension:nil];
    [self.webView loadRequest:[NSURLRequest requestWithURL:url]];

8 HTML

1.Html決定網(wǎng)頁的內容迂曲,css決定網(wǎng)頁的樣式靶橱,js決定網(wǎng)頁的事件
2.html學習網(wǎng)站:http://www.w3school.com.cn

9 OC和JS代碼的互調

01 OC調用JS的代碼
    NSString *str = [self.webView stringByEvaluatingJavaScriptFromString:@"sum()"];

02 JS怎么調用OC的說明
    新的需求:點擊按鈕的時候撥打電話
    但是我在點擊按鈕的時候,用戶是不知道的,我們怎么能夠知道用戶點擊了網(wǎng)頁上面的一個按鈕抓韩,只能通過一個技巧纠永,那就是自己搞一個特定的協(xié)議頭比如說xmg://,當我攔截到你的網(wǎng)絡請求的時候,只需要判斷一下當前的協(xié)議頭是不是這個就能判斷你現(xiàn)在是否是JS調用谒拴。
    OC里面有通過字符串生成SEL類型的方法尝江,所以當拿到數(shù)據(jù)之后做下面的事情
    1)截取方法的名稱
    2)將截取出來的字符串轉換為SEL
    3)利用performSelect方法來調用SEL

03 涉及到的相關方法
    [@"abc" hasPrefix:@"A"] //判斷字符串是否以一個固定的字符開頭,這里為A
    //截串操作
    - (NSString *)substringFromIndex:(NSUInteger)from;
    //切割字符串英上,返回一個數(shù)組
    - (NSArray<NSString *> *)componentsSeparatedByString:(NSString *)separator;
    //替換操作
    - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement
    //把string包裝成SEL

    SEL selector = NSSelectorFromString(sel);

04 如何屏蔽警告
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            //-Warc-performSelector-leaks為唯一的警告標識
            [self performSelector:selector withObject:nil];
    #pragma clang diagnostic pop

10 NSInvocation的基本使用

//封裝invacation可以調用多個參數(shù)的方法
-(void)invacation
{
    //1.創(chuàng)建一個MethodSignature炭序,簽名中保存了方法的名稱,參數(shù)和返回值
    //這個方法屬于誰苍日,那么就用誰來進行創(chuàng)建
    //注意:簽名一般是用來設置參數(shù)和獲得返回值的惭聂,和方法的調用沒有太大的關系
    NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(callWithNumber:andContext:withStatus:)];

    /*注意不要寫錯了方法名稱
     //    NSMethodSignature *signature = [ViewController methodSignatureForSelector:@selector(call)];
     */

    //2.通過MethodSignature來創(chuàng)建一個NSInvocation
    //NSInvocation中保存了方法所屬于的對象|方法名稱|參數(shù)|返回值等等
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

    /*2.1 設置invocation,來調用方法*/

    invocation.target = self;
    //    invocation.selector = @selector(call);
    //    invocation.selector = @selector(callWithNumber:);
    //    invocation.selector = @selector(callWithNumber:andContext:);
    invocation.selector = @selector(callWithNumber:andContext:withStatus:);

    NSString *number = @"10086";
    NSString *context = @"下課了";
    NSString *status = @"睡覺的時候";

    //注意:
    //1.自定義的參數(shù)索引從2開始相恃,0和1已經(jīng)被self and _cmd占用了
    //2.方法簽名中保存的方法名稱必須和調用的名稱一致
    [invocation setArgument:&number atIndex:2];
    [invocation setArgument:&context atIndex:3];
    [invocation setArgument:&status atIndex:4];

    /*3.調用invok方法來執(zhí)行*/
    [invocation invoke];
}

11 異常處理

01 一般處理方式:
    a.app異常閃退辜纲,那么捕獲crash信息,并記錄在本地沙盒中拦耐。
    b.當下次用戶重新打開app的時候耕腾,檢查沙盒中是否保存有上次捕獲到的crash信息。
    c.如果有那么利用專門的接口發(fā)送給服務器杀糯,以求在后期版本中修復扫俺。

02 如何拋出異常

    //拋出異常的兩種方式
        // @throw  [NSException exceptionWithName:@"好大一個bug" reason:@"異常原因:我也不知道" userInfo:nil];

        //方式二
        NSString *info = [NSString stringWithFormat:@"%@方法找不到",NSStringFromSelector(aSelector)];
        //下面這種方法是自動拋出的
        [NSException raise:@"這是一個異常" format:info,nil];

03 如何捕獲異常
    NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);

    void UncaughtExceptionHandler(NSException *exception) {
    NSArray *arr = [exception callStackSymbols];//得到當前調用棧信息
    NSString *reason = [exception reason];//非常重要,就是崩潰的原因
    NSString *name = [exception name];//異常類型

    NSString *errorMsg = [NSString stringWithFormat:@"當前調用棧的信息:%@\nCrash的原因:%@\n異常類型:%@\n",arr,reason,name];
    //把該信息保存到本地沙盒固翰,下次回傳給服務器狼纬。
}

補充

關于JS相關的學習框架:WebViewJavascriptBridge

12.Cocoapods的安裝

1.先升級Gem
    sudo gem update --system
2.切換cocoapods的數(shù)據(jù)源
    【先刪除,再添加骂际,查看】
    gem sources --remove https://rubygems.org/
    gem sources -a https://ruby.taobao.org/
    gem sources -l
3.安裝cocoapods
    sudo gem install cocoapods
    或者(如10.11系統(tǒng))sudo gem install -n /usr/local/bin cocoapods
4.將Podspec文件托管地址從github切換到國內的oschina
    【先刪除疗琉,再添加,再更新】
    pod repo remove master
    pod repo add master http://git.oschina.net/akuandev/Specs.git
    pod repo add master https://gitcafe.com/akuandev/Specs.git
    pod repo update
5.設置pod倉庫
    pod setup
6.測試
    【如果有版本號方援,則說明已經(jīng)安裝成功】
    pod --version
7.利用cocoapods來安裝第三方框架
    01 進入要安裝框架的項目的.xcodeproj同級文件夾
    02 在該文件夾中新建一個文件podfile
    03 在文件中告訴cocoapods需要安裝的框架信息
        a.該框架支持的平臺
        b.適用的iOS版本
        c.框架的名稱
        d.框架的版本
8.安裝
pod install --no-repo-update
pod update --no-repo-update

9.說明
platform :ios, '8.0' 用來設置所有第三方庫所支持的iOS最低版本
pod 'SDWebImage','~>2.6' 設置框架的名稱和版本號
版本號的規(guī)則:
'>1.0'    可以安裝任何高于1.0的版本
'>=1.0'   可以安裝任何高于或等于1.0的版本
'<1.0'    任何低于1.0的版本
'<=1.0'   任何低于或等于1.0的版本
'~>0.1'   任何高于或等于0.1的版本没炒,但是不包含高于1.0的版本
'~>0'     任何版本,相當于不指定版本,默認采用最新版本號

10.使用pod install命令安裝框架后的大致過程:
01 分析依賴:該步驟會分析Podfile,查看不同類庫之間的依賴情況器躏。如果有多個類庫依賴于同一個類庫种冬,但是依賴于不同的版本,那么cocoaPods會自動設置一個兼容的版本掸宛。
02 下載依賴:根據(jù)分析依賴的結果,下載指定版本的類庫到本地項目中。
03 生成Pods項目:創(chuàng)建一個Pods項目專門用來編譯和管理第三方框架呀非,CocoaPods會將所需的框架,庫等內容添加到項目中,并且進行相應的配置岸裙。
04 整合Pods項目:將Pods和項目整合到一個工作空間中猖败,并且設置文件鏈接。


/Users/StoneMan/Desktop/BuDeJie3/BuDeJie3

13.Base64補充

1.Base64簡單說明
    描述:Base64可以成為密碼學的基石降允,非常重要恩闻。
    特點:可以將任意的二進制數(shù)據(jù)進行Base64編碼
    結果:所有的數(shù)據(jù)都能被編碼為并只用65個字符就能表示的文本文件。
    65字符:A~Z a~z 0~9 + / =
    對文件進行base64編碼后文件數(shù)據(jù)的變化:編碼后的數(shù)據(jù)~=編碼前數(shù)據(jù)的4/3剧董,會大1/3左右幢尚。

2.命令行進行Base64編碼和解碼
    編碼:base64 123.png -o 123.txt
    解碼:base64 123.txt -o test.png -D

2.Base64編碼原理
    1)將所有字符轉化為ASCII碼;
    2)將ASCII碼轉化為8位二進制翅楼;
    3)將二進制3個歸成一組(不足3個在后邊補0)共24位尉剩,再拆分成4組,每組6位毅臊;
    4)統(tǒng)一在6位二進制前補兩個0湊足8位理茎;
    5)將補0后的二進制轉為十進制;
    6)從Base64編碼表獲取十進制對應的Base64編碼管嬉;

處理過程說明:
    a.轉換的時候功蜓,將三個byte的數(shù)據(jù),先后放入一個24bit的緩沖區(qū)中宠蚂,先來的byte占高位式撼。
    b.數(shù)據(jù)不足3byte的話,于緩沖區(qū)中剩下的bit用0補足求厕。然后著隆,每次取出6個bit,按照其值選擇查表選擇對應的字符作為編碼后的輸出呀癣。
    c.不斷進行美浦,直到全部輸入數(shù)據(jù)轉換完成。
    d.如果最后剩下兩個輸入數(shù)據(jù)项栏,在編碼結果后加1個“=”浦辨;
    e.如果最后剩下一個輸入數(shù)據(jù),編碼結果后加2個“=”沼沈;
    f.如果沒有剩下任何數(shù)據(jù)流酬,就什么都不要加,這樣才可以保證資料還原的正確性列另。

3.實現(xiàn)
    a.說明:
        1)從iOS7.0 開始芽腾,蘋果就提供了base64的編碼和解碼支持
        2)如果是老項目,則還能看到base64編碼和解碼的第三方框架页衙,如果當前不再支持iOS7.0以下版本摊滔,則建議替換阴绢。

    b.相關代碼:
    //給定一個字符串,對該字符串進行Base64編碼艰躺,然后返回編碼后的結果
    -(NSString *)base64EncodeString:(NSString *)string
    {
        //1.先把字符串轉換為二進制數(shù)據(jù)
        NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

        //2.對二進制數(shù)據(jù)進行base64編碼呻袭,返回編碼后的字符串
        return [data base64EncodedStringWithOptions:0];
    }

    //對base64編碼后的字符串進行解碼
    -(NSString *)base64DecodeString:(NSString *)string
    {
        //1.將base64編碼后的字符串『解碼』為二進制數(shù)據(jù)
        NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0];

        //2.把二進制數(shù)據(jù)轉換為字符串返回
        return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    }

    c.終端測試命令
        $ echo -n A | base64
        $ echo -n QQ== |base64 -D

14.加密相關

網(wǎng)絡應用程序數(shù)據(jù)的原則:

1. 在網(wǎng)絡上"不允許"傳輸用戶隱私數(shù)據(jù)的"明文"
2. 在本地"不允許"保存用戶隱私數(shù)據(jù)的"明文"

加密相關

1. base64 編碼格式
2. 密碼學演化 "秘密本"-->RSA

RSA簡單說明:加密算法算法是公開的,加密方式如下:

- "公鑰"加密腺兴,"私鑰"解密
- "私鑰"加密棒妨,"公鑰"解密

目前流行的加密方式:
---------------
- 哈希(散列)函數(shù)
    - MD5
    - SHA1
    - SHA256

- 對稱加密算法
    - DES
    - 3DES
    - AES(高級密碼標準,美國國家安全局使用的)

- 非對稱加密算法(RSA)

散列函數(shù):
---------------
特點:
    - 算法是公開的
    - "對相同的數(shù)據(jù)加密含长,得到的結果是一樣的"
    - 對不同的數(shù)據(jù)加密券腔,得到的結果是定長的,MD5對不同的數(shù)據(jù)進行加密拘泞,得到的結果都是 32 個字符長度的字符串
    - 信息摘要纷纫,信息"指紋",是用來做數(shù)據(jù)識別的陪腌!
    - 不能反算的

用途:
    - 密碼辱魁,服務器并不需要知道用戶真實的密碼!
    - 搜索
        張老師 楊老師 蒼老師
        蒼老師 張老師 楊老師

        張老師            1bdf605991920db11cbdf8508204c4eb
        楊老師             2d97fbce49977313c2aae15ea77fec0f
        蒼老師             692e92669c0ca340eff4fdcef32896ee

        如何判斷:對搜索的每個關鍵字進行三列诗鸭,得到三個相對應的結果染簇,按位相加結果如果是一樣的,那搜索的內容就是一樣的强岸!
    - 版權
        版權保護锻弓,文件的識別。

破解:
    - http://www.cmd5.com 記錄超過24萬億條蝌箍,共占用160T硬盤 的密碼數(shù)據(jù)青灼,通過對海量數(shù)據(jù)的搜索得到的結果!

提升MD5加密安全性妓盲,有兩個解決辦法
1. 加"鹽"(佐料)
2. HMAC:給定一個"秘鑰"杂拨,對明文進行加密,并且做"兩次散列"悯衬!-> 得到的結果弹沽,還是 32 個字符

總結

  • AFN會進行域名驗證
  • 命令行:
    • base64文件加密和解密
      • 加密:base64 123.png -o 123.txt
      • 解密:base64 123.txt -o test.png -D
  • base64二進制數(shù)據(jù)
    • 加密 :echo -n A |base64
    • 解密:echo -n QQ== |base64 -D
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市筋粗,隨后出現(xiàn)的幾起案子策橘,更是在濱河造成了極大的恐慌,老刑警劉巖亏狰,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件役纹,死亡現(xiàn)場離奇詭異,居然都是意外死亡暇唾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來策州,“玉大人瘸味,你說我怎么就攤上這事」还遥” “怎么了旁仿?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長孽糖。 經(jīng)常有香客問我枯冈,道長,這世上最難降的妖魔是什么办悟? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任尘奏,我火速辦了婚禮,結果婚禮上病蛉,老公的妹妹穿的比我還像新娘炫加。我一直安慰自己,他們只是感情好铺然,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布俗孝。 她就那樣靜靜地躺著,像睡著了一般魄健。 火紅的嫁衣襯著肌膚如雪赋铝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天沽瘦,我揣著相機與錄音柬甥,去河邊找鬼。 笑死其垄,一個胖子當著我的面吹牛苛蒲,可吹牛的內容都是我干的。 我是一名探鬼主播绿满,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼臂外,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喇颁?” 一聲冷哼從身側響起漏健,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎橘霎,沒想到半個月后蔫浆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡姐叁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年瓦盛,在試婚紗的時候發(fā)現(xiàn)自己被綠了洗显。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡原环,死狀恐怖挠唆,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情嘱吗,我是刑警寧澤玄组,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站谒麦,受9級特大地震影響俄讹,放射性物質發(fā)生泄漏。R本人自食惡果不足惜绕德,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一患膛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迁匠,春花似錦剩瓶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亡哄,卻和暖如春枝缔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蚊惯。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工愿卸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人截型。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓趴荸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親宦焦。 傳聞我的和親對象是個殘疾皇子发钝,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)波闹,斷路器酝豪,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 13.服務器圖片改了,url沒有變精堕,需求孵淘,服務器的圖片變了,就從服務器加載圖片歹篓,如果服務器的沒變瘫证,就從本地加載 1...
    AlanGe閱讀 1,134評論 0 1
  • 網(wǎng)絡安全(數(shù)據(jù)安全) 相關概念 安全的原則在網(wǎng)絡上不允許傳輸用戶隱私數(shù)據(jù)的明文在本地不允許保存用戶隱私數(shù)據(jù)的明文 ...
    彼岸的黑色曼陀羅閱讀 671評論 1 2
  • 1.請簡單說明多線程技術的優(yōu)點和缺點揉阎? 優(yōu)點能適當提高程序的執(zhí)行效率能適當提高資源的利用率(CPU/內存利用率) ...
    彼岸的黑色曼陀羅閱讀 451評論 0 2
  • 該文章屬于<簡書 — Timhbw>原創(chuàng),轉載請注明: <簡書社區(qū) — Timhbw>http://www.jia...
    伯虔閱讀 17,092評論 3 158