1.在開發(fā)的時候可以創(chuàng)建一個工具類逮诲,繼承自我們的AFN中的請求管理者单旁,再控制器中真正發(fā)請求的代碼使用自己封裝的工具類雹熬。
2.這樣做的優(yōu)點是以后如果修改了底層依賴的框架臣镣,那么我們修改這個工具類就可以了,而不用再一個一個的去修改谈山。
3.該工具類一般提供一個單例方法俄删,在該方法中會設(shè)置一個基本的請求路徑。
4.該方法通常還會提供對GET或POST請求的封裝奏路。
5.在外面的時候通過該工具類來發(fā)送請求
6.單例方法:
+ (instancetype)shareNetworkTools
{
static XMGNetworkTools *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//注意: BaseURL中一定要以/結(jié)尾
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)提供了一個用于文件上傳的分類畴椰。
/*文件上傳相關(guān)的代碼如下*/
-(void)upload
{
//1.創(chuàng)建一個請求管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.發(fā)送POST請求上傳數(shù)據(jù)
/*
第一個參數(shù):請求路徑:NSString類型
第二個參數(shù):要上傳的非文件參數(shù)
第三個參數(shù):block回調(diào)
在該回調(diào)中,需要利用formData拼接即將上傳的二進制數(shù)據(jù)
第三個參數(shù):上傳成功的block回調(diào)
task:dataTask(任務(wù))
responseObject:服務(wù)器返回的數(shù)據(jù)
第四個參數(shù):上傳失敗的block回調(diào)
error:錯誤信息鸽粉,如果上傳文件失敗斜脂,那么error里面包含了錯誤的描述信息
*/
NSDictionary *dict = @{
@"username":@"wenidngding"
};
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id_Nonnull formData) {
//把本地的圖片轉(zhuǎn)換為NSData類型的數(shù)據(jù)
UIImage *image = [UIImage imageNamed:@"123"];
NSData *data = UIImagePNGRepresentation(image);
/*
//拼接二進制文件數(shù)據(jù)
第一個參數(shù):要上傳的文件的二進制數(shù)據(jù)
第二個參數(shù):服務(wù)器接口規(guī)定的名稱
第三個參數(shù):這個參數(shù)上傳到服務(wù)器之后用什么名字來進行保存
第四個參數(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回調(diào)
在該回調(diào)中,需要利用formData拼接即將上傳的二進制數(shù)據(jù)
第三個參數(shù):上傳成功的block回調(diào)
task:dataTask(任務(wù))
responseObject:服務(wù)器返回的數(shù)據(jù)
第四個參數(shù):上傳失敗的block回調(diào)
error:錯誤信息触机,如果上傳文件失敗帚戳,那么error里面包含了錯誤的描述信息
*/
NSDictionary *dict = @{
@"username":@"wenidngding"
};
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id_Nonnull formData) {
//本地文件的url
NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/文頂頂/Desktop/KF[WTI`AQ3T`A@3R(B96D89.gif"];
/*
//拼接二進制文件數(shù)據(jù)
第一個參數(shù):要上傳文件的url路徑
第二個參數(shù):服務(wù)器要求的參數(shù)名稱
第三個參數(shù):這個文件上傳到服務(wù)器之后叫什么名稱
第四個參數(shù):文件的mimetype類型
第五個參數(shù):錯誤信息
*/
//[formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"xx.png" mimeType:@"application/octet-stream" error:nil];
//另外一種上傳文件的方式
/*
說明:該方法和上面的方法等價,不過該方法更加簡單其內(nèi)部會自動的的根據(jù)url路徑確定文件保存名稱儡首,并通過內(nèi)部方法獲取上傳文件的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);
}];
}
```
###3.使用AFN進行序列化處理
```objc
/*
1.AFN它內(nèi)部默認把服務(wù)器響應(yīng)的數(shù)據(jù)當(dāng)做json來進行解析片任,所以如果服務(wù)器返回給我的不是JSON數(shù)據(jù)那么請求報錯,這個時候需要設(shè)置AFN對響應(yīng)信息的解析方式蔬胯。AFN提供了三種解析響應(yīng)信息的方式对供,分別是:
1)AFXMLParserResponseSerializer----XML
2) AFHTTPResponseSerializer---------默認二進制響應(yīng)數(shù)據(jù)
3)AFJSONResponseSerializer---------JSON
2.還有一種情況就是服務(wù)器返回給我們的數(shù)據(jù)格式不太一致(開發(fā)者工具Content-Type:text/xml),那么這種情況也有可能請求不成功。解決方法:
1)直接在源代碼中修改笔宿,添加相應(yīng)的Content-Type
2)拿到這個屬性犁钟,添加到它的集合中
3.相關(guān)代碼
-(void)srializer
{
//1.創(chuàng)建請求管理者,內(nèi)部基于NSURLSession
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
/*知識點1:設(shè)置AFN采用什么樣的方式來解析服務(wù)器返回的數(shù)據(jù)*/
//如果返回的是XML泼橘,那么告訴AFN涝动,響應(yīng)的時候使用XML的方式解析
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
//如果返回的就是二進制數(shù)據(jù),那么采用默認二進制的方式來解析數(shù)據(jù)
//manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//采用JSON的方式來解析數(shù)據(jù)
//manager.responseSerializer = [AFJSONResponseSerializer serializer];
/*知識點2:告訴AFN服務(wù)器返回的數(shù)據(jù)內(nèi)容是什么類型的Content-Type*/
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/xml"];
//2.把所有的請求參數(shù)通過字典的方式來裝載炬灭,GET方法內(nèi)部會自動把所有的鍵值對取出以&符號拼接并最后用醋粟?符號連接在請求路徑后面
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.請求成功的回調(diào)block
NSLog(@"%@",[responseObject class]);
} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
//5.請求失敗的回調(diào),可以打印error的值查看錯誤信息
NSLog(@"%@",error);
}];
}
```
###4.使用AFN來檢測網(wǎng)絡(luò)狀態(tài)
```objc
/*
說明:可以使用AFN框架中的AFNetworkReachabilityManager來監(jiān)聽網(wǎng)絡(luò)狀態(tài)的改變,也可以利用蘋果提供的Reachability來監(jiān)聽米愿。建議在開發(fā)中直接使用AFN框架處理厦凤。
*/
//使用AFN框架來檢測網(wǎng)絡(luò)狀態(tài)的改變
-(void)AFNReachability
{
//1.創(chuàng)建網(wǎng)絡(luò)監(jiān)聽管理者
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
//2.監(jiān)聽網(wǎng)絡(luò)狀態(tài)的改變
/*
AFNetworkReachabilityStatusUnknown=未知
AFNetworkReachabilityStatusNotReachable=沒有網(wǎng)絡(luò)
AFNetworkReachabilityStatusReachableViaWWAN = 3G
AFNetworkReachabilityStatusReachableViaWiFi = WIFI
*/
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"沒有網(wǎng)絡(luò)");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"3G");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WIFI");
break;
default:
break;
}
}];
//3.開始監(jiān)聽
[manager startMonitoring];
}
------------------------------------------------------------
//使用蘋果提供的Reachability來檢測網(wǎng)絡(luò)狀態(tài),如果要持續(xù)監(jiān)聽網(wǎng)絡(luò)狀態(tài)的概念育苟,需要結(jié)合通知一起使用较鼓。
//提供下載地址:https://developer.apple.com/library/ios/samplecode/Reachability/Reachability.zip
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//1.注冊一個通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChange) name:kReachabilityChangedNotification object:nil];
//2.拿到一個對象,然后調(diào)用開始監(jiān)聽方法
Reachability *r = [Reachability reachabilityForInternetConnection];
[r startNotifier];
//持有該對象违柏,不要讓該對象釋放掉
self.r = r;
}
//當(dāng)控制器釋放的時候博烂,移除通知的監(jiān)聽
-(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ò)為手機自帶網(wǎng)絡(luò)");
}else
{
NSLog(@"當(dāng)前沒有網(wǎng)絡(luò)");
}
}
```
###5.數(shù)據(jù)安全
```objc
01攻城利器:Charles(公司中一般都使用該工具來抓包,并做網(wǎng)絡(luò)測試)
注意:Charles在使用中的亂碼問題漱竖,可以顯示包內(nèi)容禽篱,然后打開info.plist文件,找到j(luò)ava目錄下面的VMOptions馍惹,在后面添加一項:-Dfile.encoding=UTF-8
02 MD5消息摘要算法是不可逆的躺率。
03數(shù)據(jù)加密的方式和規(guī)范一般公司會有具體的規(guī)定,不必多花時間万矾。
```
###6.HTTPS的基本使用
```objc
1.https簡單說明
HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer)悼吱,是以安全為目標(biāo)的HTTP通道,簡單講是HTTP的安全版勤众。
即HTTP下加入SSL層舆绎,HTTPS的安全基礎(chǔ)是SSL鲤脏,因此加密的詳細內(nèi)容就需要SSL们颜。它是一個URI scheme(抽象標(biāo)識符體系),句法類同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é)議構(gòu)建的可進行加密傳輸褪贵、身份認證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全抗俄。
3.對開發(fā)的影響竭鞍。
3.1如果是自己使用NSURLSession來封裝網(wǎng)絡(luò)請求,涉及代碼如下橄镜。
- (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的,就會調(diào)用這個代理方法
我們需要在該方法中告訴系統(tǒng),是否信任服務(wù)器返回的證書
Challenge:挑戰(zhàn)質(zhì)問(包含了受保護的區(qū)域)
protectionSpace :受保護區(qū)域
NSURLAuthenticationMethodServerTrust :證書的類型是服務(wù)器信任
了解:證書有好幾種偎快,一種是被認證過的一種是沒有被認證過的,如果證書是被認證過的洽胶,那么只需要信任一次就可以了晒夹,如果是沒有被認證過的,那么每次都需要重新認證
*/
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
//NSLog(@"didReceiveChallenge %@", challenge.protectionSpace);
NSLog(@"調(diào)用了最外層");
// 1.判斷服務(wù)器返回的證書類型,是否是服務(wù)器信任
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSLog(@"調(diào)用了里面這一層是服務(wù)器信任的證書");
/*
NSURLSessionAuthChallengeUseCredential = 0,使用證書
NSURLSessionAuthChallengePerformDefaultHandling = 1,忽略證書(默認的處理方式)
NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,忽略書證,并取消這次請求
NSURLSessionAuthChallengeRejectProtectionSpace = 3,忽略當(dāng)前這一次,下一次再詢問
*/
//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的基本使用
```objc
1概念性知識
01 webView是有缺點的翔横,會導(dǎo)致內(nèi)存泄露读跷,而且這個問題是它系統(tǒng)本身的問題。
02手機上面的safai其實就是用webView來實現(xiàn)的
03現(xiàn)在的開發(fā)并不完全是原生的開發(fā)禾唁,而更加傾向于原生+Html5的方式
04 webView是OC代碼和html代碼之間進行交互的橋梁
2代碼相關(guān)
/*A*網(wǎng)頁操控相關(guān)方法**/
[self.webView goBack];回退
[self.webView goForward];前進
[self.webView reload];刷新
//設(shè)置是否能夠前進和回退
self.goBackBtn.enabled = webView.canGoBack;
self.fowardBtn.enabled = webView.canGoForward;
/*B*常用的屬性設(shè)置**/
self.webView.scalesPageToFit = YES;設(shè)置網(wǎng)頁自動適應(yīng)
self.webView.dataDetectorTypes = UIDataDetectorTypeAll;設(shè)置檢測網(wǎng)頁中的格式類型效览,all表示檢測所有類型包括超鏈接、電話號碼荡短、地址等丐枉。
self.webView.scrollView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);
/*C*相關(guān)代理方法**/
//每當(dāng)將加載請求的時候調(diào)用該方法,返回YES表示加載該請求掘托,返回NO表示不加載該請求
//可以在該方法中攔截請求
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return ![request.URL.absoluteString containsString:@"dushu"];
}
//開始加載網(wǎng)頁瘦锹,不僅監(jiān)聽我們指定的請求,還會監(jiān)聽內(nèi)部發(fā)送的請求
-(void)webViewDidStartLoad:(UIWebView *)webView
//網(wǎng)頁加載完畢之后會調(diào)用該方法
-(void)webViewDidFinishLoad:(UIWebView *)webView
//網(wǎng)頁加載失敗調(diào)用該方法
-(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
```objc
1.Html決定網(wǎng)頁的內(nèi)容闪盔,css決定網(wǎng)頁的樣式弯院,js決定網(wǎng)頁的事件
2.html學(xué)習(xí)網(wǎng)站:http://www.w3school.com.cn
```
####9 OC和JS代碼的互調(diào)
```objc
01 OC調(diào)用JS的代碼
NSString *str = [self.webView stringByEvaluatingJavaScriptFromString:@"sum()"];
02 JS怎么調(diào)用OC的說明
新的需求:點擊按鈕的時候撥打電話
但是我在點擊按鈕的時候,用戶是不知道的泪掀,我們怎么能夠知道用戶點擊了網(wǎng)頁上面的一個按鈕听绳,只能通過一個技巧,那就是自己搞一個特定的協(xié)議頭比如說xmg://,當(dāng)我攔截到你的網(wǎng)絡(luò)請求的時候族淮,只需要判斷一下當(dāng)前的協(xié)議頭是不是這個就能判斷你現(xiàn)在是否是JS調(diào)用辫红。
OC里面有通過字符串生成SEL類型的方法凭涂,所以當(dāng)拿到數(shù)據(jù)之后做下面的事情
1)截取方法的名稱
2)將截取出來的字符串轉(zhuǎn)換為SEL
3)利用performSelect方法來調(diào)用SEL
03涉及到的相關(guān)方法
[@"abc" hasPrefix:@"A"] //判斷字符串是否以一個固定的字符開頭,這里為A
//截串操作
- (NSString *)substringFromIndex:(NSUInteger)from;
//切割字符串贴妻,返回一個數(shù)組
- (NSArray *)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)識
[self performSelector:selector withObject:nil];
#pragma clang diagnostic pop
```
####9 NSInvocation的基本使用
```objc
//封裝invacation可以調(diào)用多個參數(shù)的方法
-(void)invacation
{
//1.創(chuàng)建一個MethodSignature切油,簽名中保存了方法的名稱,參數(shù)和返回值
//這個方法屬于誰名惩,那么就用誰來進行創(chuàng)建
//注意:簽名一般是用來設(shè)置參數(shù)和獲得返回值的澎胡,和方法的調(diào)用沒有太大的關(guān)系
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設(shè)置invocation,來調(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 = @"睡覺的時候";
//注意:
//1.自定義的參數(shù)索引從2開始娩鹉,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方法來執(zhí)行*/
[invocation invoke];
}
```
####10異常處理
```objc
01一般處理方式:
a.app異常閃退攻谁,那么捕獲crash信息,并記錄在本地沙盒中弯予。
b.當(dāng)下次用戶重新打開app的時候戚宦,檢查沙盒中是否保存有上次捕獲到的crash信息。
c.如果有那么利用專門的接口發(fā)送給服務(wù)器锈嫩,以求在后期版本中修復(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];//得到當(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ù)器艳汽。
}