什么是MD5
MD5的特点
MD5的应用
MD5解密网站:http://www.cmd5.com
#pragma mark - NSURLSessionDataDelegate
// 只要访问的是HTTPS的路径就会调用
// 该方法的作用就是处理服务器返回的证书, 需要在该方法中告诉系统是否需要安装服务器返回的证书
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
// 1.从服务器返回的受保护空间中拿到证书的类型
// 2.判断服务器返回的证书是否是服务器信任的
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSLog(@"是服务器信任的证书");
// 3.根据服务器返回的受保护空间创建一个证书
// void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)
// 代理方法的completionHandler block接收两个参数:
// 第一个参数: 代表如何处理证书
// 第二个参数: 代表需要处理哪个证书
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
// 4.安装证书
completionHandler(NSURLSessionAuthChallengeUseCredential , credential);
}
}
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 用于调整界面
self.webView.scalesPageToFit = YES;
// 1.加载网页
[self.webView loadRequest:request];
NSURL *url = [[NSBundle mainBundle] URLForResource:@"test.html" withExtension:nil];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 用于识别网页中的特殊符号
self.webView.dataDetectorTypes = UIDataDetectorTypeAll;
[self.webView loadRequest:request];
NSURL *url = [NSURL fileURLWithPath:filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
#pragma mark - UIWebViewDelegate
// 每次即将加载一个新的资源都会调用
// 如果返回YES, 代表允许加载当前资源
// 如果返回NO, 代表不允许加载当前资源
// JS和OC进行互相调用
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// NSLog(@"%@", request.URL);
return YES;
}
// 开始加载
// 只要webview加载一个资源就会调用一次
- (void)webViewDidStartLoad:(UIWebView *)webView
{
}
// 加载完毕
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// 设置前进后退按钮的状态
self.gobackBtn.enabled = [self.webView canGoBack];
self.goforwardBtn.enabled = [self.webView canGoForward];
}
// 加载出错
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(@"%@", error);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [[NSBundle mainBundle] URLForResource:@"test.html" withExtension:nil];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// OC调用JS,利用UIWebView的stringByEvaluatingJavaScriptFromString方法, 告诉系统需要调用的JS方法名称即可
[self.webView stringByEvaluatingJavaScriptFromString:@"showTitle();"];
}
#pragma mark - UIWebViewDelegate
// 利用该方法作为JS和OC之间的桥梁
// 在JS跳转网页
// 在OC代理方法中通过判断自定义协议头, 决定是否是JS调用OC方法
// 在OC代理方法中通过截取字符串, 获取JS想调用的OC方法名称
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// NSLog(@"%@", request.URL);
NSString *schem = @"xmg://";
NSString *urlStr = request.URL.absoluteString;
if ([urlStr hasPrefix:schem]) {
NSLog(@"需要调用OC方法");
// 1.从URL中获取方法名称
// xmg://call
NSString *methodName = [urlStr substringFromIndex:schem.length];
NSLog(@"%@", methodName);
// 2.调用方法
SEL sel = NSSelectorFromString(methodName);
// 忽略警告信息的作用范围开始
#pragma clang diagnostic push
// 下面这一行代码是用于指定需要忽略的警告信息
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:sel withObject:nil];
// 忽略警告信息的作用范围结束
#pragma clang diagnostic pop
return NO;
}
return YES;
}
NSString *schem = @"xmg://";
NSString *urlStr = request.URL.absoluteString;
if ([urlStr hasPrefix:schem]) {
NSLog(@"需要调用OC方法");
// 1.从URL中获取方法名称
// xmg://sendMessageWithNumber_andContent_?10086&love
NSString *subPath = [urlStr substringFromIndex:schem.length];
// 注意: 如果指定的用于切割的字符串不存在, 那么就会返回整个字符串
NSArray *subPaths = [subPath componentsSeparatedByString:@"?"];
// 2.获取方法名称
NSString *methodName = [subPaths firstObject];
methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"];
NSLog(@"%@", methodName);
// 2.调用方法
SEL sel = NSSelectorFromString(methodName);
// 3.处理参数
NSString *parma = nil;
if (subPaths.count == 2) {
parma = [subPaths lastObject];
// 3.截取参数
NSArray *parmas = [parma componentsSeparatedByString:@"&"];
[self performSelector:sel withObject:[parmas firstObject] withObject:[parmas lastObject]];
return NO;
}
[self performSelector:sel withObject:parma];
return NO;
}
多个参数的情况下,使用不方便,引出下节使用NSInvocation
// Signature签名: 在创建NSInvocation的时候, 必须传递一个签名对象
// 签名对象的作用 : 用于获取参数的个数和方法的返回值
// 注意点: 创建签名对象的时候不是使用NSMethodSignature类创建,而是方法属于谁就用谁来创建
- (void)viewDidLoad {
[super viewDidLoad];
// 1.创建一个NSInvocation对象
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self; // 保存方法所属的对象
// 给invocation设置的方法, 必须和签名中的方法一致
invocation.selector = @selector(sendMessageWithNumber:andContent:status:); // 保存方法名称
// 第一个参数: 需要给指定方法传递的值
// + 第一个参数需要接收一个指针, 也就是传递值的时候需要传递地址
// 第二个参数: 需要给指定方法的第几个参数传值
NSString *number = @"10086";
// 注意: 设置参数的索引时不能从0开始, 因为0已经被self占用, 1已经被_cmd占用
[invocation setArgument:&number atIndex:2];
NSString *content = @"love";
[invocation setArgument:&content atIndex:3];
NSString *status = @"success";
[invocation setArgument:&status atIndex:4];
// 2.调用NSInvocation对象的invoke方法
// 只要调用invocation的invoke方法, 就代表需要执行 \
NSInvocation对象中指定对象的指定方法, 并且传递指定的参数
[invocation invoke];
}
- (id)performSelector:(SEL)aSelector withObjects:(NSArray *)objects
{
// 1.创建签名对象
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:aSelector];
// 判断传入的方法是否存储, 如果方法不存在签名对象为nil
if (signature == nil) {
// 传入的方法不存在
NSString *info = [NSString stringWithFormat:@" -[%@ %@]: unrecognized selector sent to instance", [self class], NSStringFromSelector(aSelector)];
// 直接抛异常
@throw [[NSException alloc] initWithName:@"一个牛B的错误" reason:info userInfo:nil];
}
// 2.创建一个NSInvocation对象
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
// 3.保存方法所属的对象
invocation.target = self;
// 给invocation设置的方法, 必须和签名中的方法一致
// 4.保存方法名称
invocation.selector = aSelector;
// 5.设置参数
/*
当前如果直接遍历参数数组来设置参数, 会存在问题
如果参数数组元素多余参数个数, 那么就会报错
*/
NSUInteger arguments = signature.numberOfArguments - 2;
/*
如果直接遍历参数值的个数, 会存在问题
如果参数的个数大于了参数值的个数, 那么数组会越界
*/
NSUInteger objectsCount = objects.count;
/*
参数和参数值, 谁少就遍历谁
*/
NSUInteger count = MIN(arguments, objectsCount);
for (int i = 0; i < count; i++) {
NSObject *obj = objects[i];
// 处理数组参数中NSNull问题
if ([obj isKindOfClass:[NSNull class]]) {
obj = nil;
}
[invocation setArgument:&obj atIndex:i + 2];
}
// 6.调用NSInvocation对象的invoke方法
[invocation invoke];
id res = nil;
// 判断当前方法是否有返回值
if ( signature.methodReturnLength != 0) {
// 7.获取返回值
// getReturnValue方法会将会去到的方法返回值赋值给传入的对象
[invocation getReturnValue:&res];
}
return res;
}