iOS之網(wǎng)絡(luò)篇(你知道這些零碎的知識(shí)嗎?)

1.AFN使用技巧

1.在開(kāi)發(fā)的時(shí)候可以創(chuàng)建一個(gè)工具類,繼承自我們的AFN中的請(qǐng)求管理者,再控制器中真正發(fā)請(qǐng)求的代碼使用自己封裝的工具類。
2.這樣做的優(yōu)點(diǎn)是以后如果修改了底層依賴的框架,那么我們修改這個(gè)工具類就可以了,而不用再一個(gè)一個(gè)的去修改。
3.該工具類一般提供一個(gè)單例方法,在該方法中會(huì)設(shè)置一個(gè)基本的請(qǐng)求路徑。
4.該方法通常還會(huì)提供對(duì)GET或POST請(qǐng)求的封裝。
5.在外面的時(shí)候通過(guò)該工具類來(lái)發(fā)送請(qǐng)求
6.單例方法:
+ (instancetype)shareNetworkTools
{
    static XMGNetworkTools *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 注意: BaseURL中一定要以/結(jié)尾
        instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"http://地址/"]];
    });
    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)提供了一個(gè)用于文件上傳的分類。

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

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

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

    [manager POST:@"http://服務(wù)器地址" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

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

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

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

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

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

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

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

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

    [manager POST:@"http://服務(wù)器地址" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {

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

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


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

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

3.使用AFN進(jìn)行序列化處理

/*
1.AFN它內(nèi)部默認(rèn)把服務(wù)器響應(yīng)的數(shù)據(jù)當(dāng)做json來(lái)進(jìn)行解析,所以如果服務(wù)器返回給我的不是JSON數(shù)據(jù)那么請(qǐng)求報(bào)錯(cuò),這個(gè)時(shí)候需要設(shè)置AFN對(duì)響應(yīng)信息的解析方式。AFN提供了三種解析響應(yīng)信息的方式,分別是:
1)AFXMLParserResponseSerializer----XML
2) AFHTTPResponseSerializer---------默認(rèn)二進(jìn)制響應(yīng)數(shù)據(jù)
3)AFJSONResponseSerializer---------JSON

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

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

    /* 知識(shí)點(diǎn)1:設(shè)置AFN采用什么樣的方式來(lái)解析服務(wù)器返回的數(shù)據(jù)*/

    //如果返回的是XML,那么告訴AFN,響應(yīng)的時(shí)候使用XML的方式解析
    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

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

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


    /*知識(shí)點(diǎn)2: 告訴AFN服務(wù)器返回的數(shù)據(jù)內(nèi)容是什么類型的 Content-Type*/
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/xml"];

    //2.把所有的請(qǐng)求參數(shù)通過(guò)字典的方式來(lái)裝載,GET方法內(nèi)部會(huì)自動(dòng)把所有的鍵值對(duì)取出以&符號(hào)拼接并最后用?符號(hào)連接在請(qǐng)求路徑后面
    NSDictionary *dict = @{
                           @"username":@"223",
                           @"pwd":@"ewr",
                           @"type":@"XML"
                           };

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

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

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

4.使用AFN來(lái)檢測(cè)網(wǎng)絡(luò)狀態(tài)

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

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

            default:
                break;
        }
    }];

    //3.開(kāi)始監(jiān)聽(tīng)
    [manager startMonitoring];
}

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

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

    //2.拿到一個(gè)對(duì)象,然后調(diào)用開(kāi)始監(jiān)聽(tīng)方法
    Reachability *r = [Reachability reachabilityForInternetConnection];
    [r startNotifier];

    //持有該對(duì)象,不要讓該對(duì)象釋放掉
    self.r = r;
}

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

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

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

01 攻城利器:Charles(公司中一般都使用該工具來(lái)抓包,并做網(wǎng)絡(luò)測(cè)試)
注意:Charles在使用中的亂碼問(wèn)題,可以顯示包內(nèi)容,然后打開(kāi)info.plist文件,找到j(luò)ava目錄下面的VMOptions,在后面添加一項(xiàng):-Dfile.encoding=UTF-8
02 MD5消息摘要算法是不可逆的。
03 數(shù)據(jù)加密的方式和規(guī)范一般公司會(huì)有具體的規(guī)定,不必多花時(shí)間。

6.HTTPS的基本使用

1.https簡(jiǎn)單說(shuō)明
    HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標(biāo)的HTTP通道,簡(jiǎn)單講是HTTP的安全版。
    即HTTP下加入SSL層,HTTPS的安全基礎(chǔ)是SSL,因此加密的詳細(xì)內(nèi)容就需要SSL。 它是一個(gè)URI scheme(抽象標(biāo)識(shí)符體系),句法類同http:體系。用于安全的HTTP數(shù)據(jù)傳輸。
    https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默認(rèn)端口及一個(gè)加密/身份驗(yàn)證層(在HTTP與TCP之間)。

2.HTTPS和HTTP的區(qū)別主要為以下四點(diǎn):
        一、https協(xié)議需要到ca申請(qǐng)證書(shū),一般免費(fèi)證書(shū)很少,需要交費(fèi)。
        二、http是超文本傳輸協(xié)議,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協(xié)議。
        三、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
        四、http的連接很簡(jiǎn)單,是無(wú)狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。

3.對(duì)開(kāi)發(fā)的影響。
3.1 如果是自己使用NSURLSession來(lái)封裝網(wǎng)絡(luò)請(qǐ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];
}

/*
 只要請(qǐng)求的地址是HTTPS的, 就會(huì)調(diào)用這個(gè)代理方法
 我們需要在該方法中告訴系統(tǒng), 是否信任服務(wù)器返回的證書(shū)
 Challenge: 挑戰(zhàn) 質(zhì)問(wèn) (包含了受保護(hù)的區(qū)域)
 protectionSpace : 受保護(hù)區(qū)域
 NSURLAuthenticationMethodServerTrust : 證書(shū)的類型是 服務(wù)器信任
 了解:證書(shū)有好幾種,一種是被認(rèn)證過(guò)的一種是沒(méi)有被認(rèn)證過(guò)的,如果證書(shū)是被認(rèn)證過(guò)的,那么只需要信任一次就可以了,如果是沒(méi)有被認(rèn)證過(guò)的,那么每次都需要重新認(rèn)證
 */
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
    //    NSLog(@"didReceiveChallenge %@", challenge.protectionSpace);
    NSLog(@"調(diào)用了最外層");
    // 1.判斷服務(wù)器返回的證書(shū)類型, 是否是服務(wù)器信任
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSLog(@"調(diào)用了里面這一層是服務(wù)器信任的證書(shū)");
        /*
         NSURLSessionAuthChallengeUseCredential = 0,                     使用證書(shū)
         NSURLSessionAuthChallengePerformDefaultHandling = 1,            忽略證書(shū)(默認(rèn)的處理方式)
         NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,     忽略書(shū)證, 并取消這次請(qǐng)求
         NSURLSessionAuthChallengeRejectProtectionSpace = 3,            忽略當(dāng)前這一次, 下一次再詢問(wèn)
         */
//        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

        NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];

        completionHandler(NSURLSessionAuthChallengeUseCredential , card);
    }
}

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

7 WebView的基本使用

1 概念性知識(shí)
    01 webView是有缺點(diǎn)的,會(huì)導(dǎo)致內(nèi)存泄露,而且這個(gè)問(wèn)題是它系統(tǒng)本身的問(wèn)題。
    02 手機(jī)上面的safai其實(shí)就是用webView來(lái)實(shí)現(xiàn)的
    03 現(xiàn)在的開(kāi)發(fā)并不完全是原生的開(kāi)發(fā),而更加傾向于原生+Html5的方式
    04 webView是OC代碼和html代碼之間進(jìn)行交互的橋梁

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

    //設(shè)置是否能夠前進(jìn)和回退
    self.goBackBtn.enabled = webView.canGoBack;
    self.fowardBtn.enabled = webView.canGoForward;

/*B*常用的屬性設(shè)置**/
    self.webView.scalesPageToFit = YES; 設(shè)置網(wǎng)頁(yè)自動(dòng)適應(yīng)
    self.webView.dataDetectorTypes = UIDataDetectorTypeAll; 設(shè)置檢測(cè)網(wǎng)頁(yè)中的格式類型,all表示檢測(cè)所有類型包括超鏈接、電話號(hào)碼、地址等。
    self.webView.scrollView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);

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

    //開(kāi)始加載網(wǎng)頁(yè),不僅監(jiān)聽(tīng)我們指定的請(qǐng)求,還會(huì)監(jiān)聽(tīng)內(nèi)部發(fā)送的請(qǐng)求
    -(void)webViewDidStartLoad:(UIWebView *)webView

    //網(wǎng)頁(yè)加載完畢之后會(huì)調(diào)用該方法
    -(void)webViewDidFinishLoad:(UIWebView *)webView

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

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

8 HTML

1.Html決定網(wǎng)頁(yè)的內(nèi)容,css決定網(wǎng)頁(yè)的樣式,js決定網(wǎng)頁(yè)的事件
2.html學(xué)習(xí)網(wǎng)站:http://www.w3school.com.cn

9 OC和JS代碼的互調(diào)

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

02 JS怎么調(diào)用OC的說(shuō)明
    新的需求:點(diǎn)擊按鈕的時(shí)候撥打電話
    但是我在點(diǎn)擊按鈕的時(shí)候,用戶是不知道的,我們?cè)趺茨軌蛑烙脩酎c(diǎn)擊了網(wǎng)頁(yè)上面的一個(gè)按鈕,只能通過(guò)一個(gè)技巧,那就是自己搞一個(gè)特定的協(xié)議頭比如說(shuō)xmg://,當(dāng)我攔截到你的網(wǎng)絡(luò)請(qǐng)求的時(shí)候,只需要判斷一下當(dāng)前的協(xié)議頭是不是這個(gè)就能判斷你現(xiàn)在是否是JS調(diào)用。
    OC里面有通過(guò)字符串生成SEL類型的方法,所以當(dāng)拿到數(shù)據(jù)之后做下面的事情
    1)截取方法的名稱
    2)將截取出來(lái)的字符串轉(zhuǎn)換為SEL
    3)利用performSelect方法來(lái)調(diào)用SEL

03 涉及到的相關(guān)方法
    [@"abc" hasPrefix:@"A"] //判斷字符串是否以一個(gè)固定的字符開(kāi)頭,這里為A
    //截串操作
    - (NSString *)substringFromIndex:(NSUInteger)from;
    //切割字符串,返回一個(gè)數(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為唯一的警告標(biāo)識(shí)
            [self performSelector:selector withObject:nil];
    #pragma clang diagnostic pop

9 NSInvocation的基本使用

//封裝invacation可以調(diào)用多個(gè)參數(shù)的方法
-(void)invacation
{
    //1.創(chuàng)建一個(gè)MethodSignature,簽名中保存了方法的名稱,參數(shù)和返回值
    //這個(gè)方法屬于誰(shuí),那么就用誰(shuí)來(lái)進(jìn)行創(chuàng)建
    //注意:簽名一般是用來(lái)設(shè)置參數(shù)和獲得返回值的,和方法的調(diào)用沒(méi)有太大的關(guān)系
    NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(callWithNumber:andContext:withStatus:)];

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

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

    /*2.1 設(shè)置invocation,來(lái)調(diào)用方法*/

    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 = @"睡覺(jué)的時(shí)候";

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

    /*3.調(diào)用invok方法來(lái)執(zhí)行*/
    [invocation invoke];
}

10 異常處理

01 一般處理方式:
    a.app異常閃退,那么捕獲crash信息,并記錄在本地沙盒中。
    b.當(dāng)下次用戶重新打開(kāi)app的時(shí)候,檢查沙盒中是否保存有上次捕獲到的crash信息。
    c.如果有那么利用專門(mén)的接口發(fā)送給服務(wù)器,以求在后期版本中修復(fù)。

02 如何拋出異常

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

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

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

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

    NSString *errorMsg = [NSString stringWithFormat:@"當(dāng)前調(diào)用棧的信息:%@\nCrash的原因:%@\n異常類型:%@\n",arr,reason,name];
    //把該信息保存到本地沙盒,下次回傳給服務(wù)器。
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.在開(kāi)發(fā)的時(shí)候可以創(chuàng)建一個(gè)工具類,繼承自我們的AFN中的請(qǐng)求管理者,再控制器中真正發(fā)請(qǐng)求的代碼使用自己封裝的工具...
    紅樓那一場(chǎng)夢(mèng)閱讀 3,627評(píng)論 2 3
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,410評(píng)論 4 61
  • 我是一個(gè)初當(dāng)HR的小菜鳥(niǎo),初創(chuàng)公司,兼職行政人事,身邊沒(méi)有資深HR可以請(qǐng)教。自己摸著石頭過(guò)河,有想法不對(duì)的地...
    王華華在路上閱讀 290評(píng)論 0 0
  • High Trail Vanoise退賽小記 1.比賽概述 2.技術(shù)小結(jié) 3.比賽經(jīng)歷 ===1.比賽概述=== ...
    陳張弛閱讀 982評(píng)論 0 3
  • 我在這寂寞的夜里不?;叵?今天的我是否依然愛(ài)你 我知道 我是個(gè)猶豫不決的懦夫 我曾擁抱著你 像你信誓旦旦的保證 如...
    水澗竹淵閱讀 410評(píng)論 1 2

友情鏈接更多精彩內(nèi)容