1.AFN使用技巧
1.在开发的时候可以创建一个工具类,继承自我们的AFN中的请求管理者,再控制器中真正发请求的代码使用自己封装的工具类。
2.这样做的优点是以后如果修改了底层依赖的框架,那么我们修改这个工具类就可以了,而不用再一个一个的去修改。
3.该工具类一般提供一个单例方法,在该方法中会设置一个基本的请求路径。
4.该方法通常还会提供对GET或POST请求的封装。
5.在外面的时候通过该工具类来发送请求
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.文件上传拼接数据的第一种方式
[formData appendPartWithFileData:data name:@"file" fileName:@"xxoo.png" mimeType:@"application/octet-stream"];
2.文件上传拼接数据的第二种方式
[formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"xx.png" mimeType:@"application/octet-stream" error:nil];
3.文件上传拼接数据的第三种方式
[formData appendPartWithFileURL:fileUrl name:@"file" error:nil];
4.【注】在资料中已经提供了一个用于文件上传的分类。
-(void)upload
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSDictionary *dict = @{
@"username":@"wenidngding"
};
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
UIImage *image = [UIImage imageNamed:@"123"];
NSData *data = UIImagePNGRepresentation(image);
[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__);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSDictionary *dict = @{
@"username":@"wenidngding"
};
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/文顶顶/Desktop/KF[WTI`AQ3T`A@3R(B96D89.gif"];
[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进行序列化处理
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
manager.responseSerializer.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);
}];
}
4.使用AFN来检测网络状态
-(void)AFNReachability
{
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"没有网络");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"3G");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WIFI");
break;
default:
break;
}
}];
[manager startMonitoring];
}
------------------------------------------------------------
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChange) name:kReachabilityChangedNotification object:nil];
Reachability *r = [Reachability reachabilityForInternetConnection];
[r startNotifier];
self.r = r;
}
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)networkChange
{
if([Reachability reachabilityForLocalWiFi].currentReachabilityStatus != NotReachable)
{
NSLog(@"当前网络为WIFI");
}else if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus != NotReachable)
{
NSLog(@"当前网络为手机自带网络");
}else
{
NSLog(@"当前没有网络");
}
}
5.数据安全
01 攻城利器:Charles(公司中一般都使用该工具来抓包,并做网络测试)
注意:Charles在使用中的乱码问题,可以显示包内容,然后打开info.plist文件,找到java目录下面的VMOptions,在后面添加一项:-Dfile.encoding=UTF-8
02 MD5消息摘要算法是不可逆的。
03 数据加密的方式和规范一般公司会有具体的规定,不必多花时间。
6.HTTPS的基本使用
1.https简单说明
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。
https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
2.HTTPS和HTTP的区别主要为以下四点:
一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
3.对开发的影响。
3.1 如果是自己使用NSURLSession来封装网络请求,涉及代码如下。
- (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];
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
NSLog(@"调用了最外层");
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSLog(@"调用了里面这一层是服务器信任的证书");
NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential , card);
}
}
3.2 如果是使用AFN框架,那么我们不需要做任何额外的操作,AFN内部已经做了处理。
7 WebView的基本使用
1 概念性知识
01 webView是有缺点的,会导致内存泄露,而且这个问题是它系统本身的问题。
02 手机上面的safai其实就是用webView来实现的
03 现在的开发并不完全是原生的开发,而更加倾向于原生+Html5的方式
04 webView是OC代码和html代码之间进行交互的桥梁
2 代码相关
[self.webView goBack]; 回退
[self.webView goForward]; 前进
[self.webView reload]; 刷新
self.goBackBtn.enabled = webView.canGoBack;
self.fowardBtn.enabled = webView.canGoForward;
self.webView.scalesPageToFit = YES; 设置网页自动适应
self.webView.dataDetectorTypes = UIDataDetectorTypeAll; 设置检测网页中的格式类型,all表示检测所有类型包括超链接、电话号码、地址等。
self.webView.scrollView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return ![request.URL.absoluteString containsString:@"dushu"];
}
-(void)webViewDidStartLoad:(UIWebView *)webView
-(void)webViewDidFinishLoad:(UIWebView *)webView
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
NSURL *url = [[NSBundle mainBundle] URLForResource:@"text.html" withExtension:nil];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
8 HTML
1.Html决定网页的内容,css决定网页的样式,js决定网页的事件
2.html学习网站:http://www.w3school.com.cn
9 OC和JS代码的互调
01 OC调用JS的代码
NSString *str = [self.webView stringByEvaluatingJavaScriptFromString:@"sum()"];
02 JS怎么调用OC的说明
新的需求:点击按钮的时候拨打电话
但是我在点击按钮的时候,用户是不知道的,我们怎么能够知道用户点击了网页上面的一个按钮,只能通过一个技巧,那就是自己搞一个特定的协议头比如说xmg:
OC里面有通过字符串生成SEL类型的方法,所以当拿到数据之后做下面的事情
1)截取方法的名称
2)将截取出来的字符串转换为SEL
3)利用performSelect方法来调用SEL
03 涉及到的相关方法
[@"abc" hasPrefix:@"A"]
- (NSString *)substringFromIndex:(NSUInteger)from;
- (NSArray<NSString *> *)componentsSeparatedByString:(NSString *)separator;
- (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement
SEL selector = NSSelectorFromString(sel);
04 如何屏蔽警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:selector withObject:nil];
#pragma clang diagnostic pop
10 NSInvocation的基本使用
-(void)invacation
{
NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(callWithNumber:andContext:withStatus:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = @selector(callWithNumber:andContext:withStatus:);
NSString *number = @"10086";
NSString *context = @"下课了";
NSString *status = @"睡觉的时候";
[invocation setArgument:&number atIndex:2];
[invocation setArgument:&context atIndex:3];
[invocation setArgument:&status atIndex:4];
[invocation invoke];
}
11 异常处理
01 一般处理方式:
a.app异常闪退,那么捕获crash信息,并记录在本地沙盒中。
b.当下次用户重新打开app的时候,检查沙盒中是否保存有上次捕获到的crash信息。
c.如果有那么利用专门的接口发送给服务器,以求在后期版本中修复。
02 如何抛出异常
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