1.对于cell而言,使用自动布局和高度缓存哪种方式比较好,为什么
1.使用自动布局会根据给出的约束,在运行时对约束的描述信息进行求解,最终使用frame来绘制视图
2.iOS应用的视图要保持60fps的刷新帧率,那么必须在16.67ms之内完成包括布局,绘制以及渲染等操作,由于自动布局本身的计算量非常巨大,而且还有设置frame的过程消耗时间,那么当页面上的视图非常多的时候,自动布局就无法达到绝对流畅的要求
3.由于自动布局的实现原理导致他的时间复杂度为多项式时间,其性能损耗是仅使用frame的十几倍,所以,在处理庞大的UI界面时表现差强人意
4.强制视图在主线程上布局
2.UIWebView和WKWebView的区别
1.对于UIWebView而言 js的alert是可以直接执行的,而在WKWebView上,js弹窗是弹不出来的,需要通过WKUIDelegate协议接收弹窗事件,然后通过iOS原生弹窗runJavaScriptAlertPanel
2.UIWebView接受一个js字符串参数 返回一个字符串,同步执行
WKWebView接受一个js字符串参数 返回一个ID类型参数 异步执行
3.WKWebView js调用OC的方法使用交互管理WKUserContentController 注册方法 在didReceiveScriptMessage里面具体实现
4. WKWebView使用WKWebViewConfiguration可以设置一些属性 轻松的对载入的网页进行一些简单高效的配置
5.WKWebView的占用内存更小,加载速度比UIWebView更快
6.WKWebView的cookie问题很难处理 与js的交互不够灵活
//创建网页配置对象
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 创建设置对象
WKPreferences *preference = [[WKPreferences alloc]init];
//最小字体大小 当将javaScriptEnabled属性设置为NO时,可以看到明显的效果
preference.minimumFontSize = 0;
//设置是否支持javaScript 默认是支持的
preference.javaScriptEnabled = YES;
// 在iOS上默认为NO,表示是否允许不经过用户交互由javaScript自动打开窗口
preference.javaScriptCanOpenWindowsAutomatically = YES;
config.preferences = preference;
// 是使用H5的视频播放器在线播放, 还是使用原生播放器全屏播放
config.allowsInlineMediaPlayback = YES;
//设置视频是否需要用户手动播放 设置为NO则会允许自动播放
config.requiresUserActionForMediaPlayback = YES;
//设置是否允许画中画技术 在特定设备上有效
config.allowsPictureInPictureMediaPlayback = YES;
//设置请求的User-Agent信息中应用程序名称 iOS9后可用
config.applicationNameForUserAgent = @"ChinaDailyForiPad";
3.使用WKWebView进行和js的交互
1.oc调用js方法
使用evaluateJavaScript
//changeColor()是JS方法名,completionHandler是异步回调block
NSString *jsString = [NSString stringWithFormat:@"changeColor('%@')", @"Js参数"];
[_webView evaluateJavaScript:jsString completionHandler:^(id _Nullable data, NSError * _Nullable error) {
NSLog(@"改变HTML的背景色");
}];
1.js调用oc方法
//这个类主要用来做native与JavaScript的交互管理
WKUserContentController * wkUController = [[WKUserContentController alloc] init];
//注册一个name为jsToOcNoPrams的js方法,设置处理接收JS方法的代理
[wkUController addScriptMessageHandler:self name:@"jsToOcNoPrams"];
[wkUController addScriptMessageHandler:self name:@"jsToOcWithPrams"];
config.userContentController = wkUController;
注意:遵守WKScriptMessageHandler协议,代理是由WKUserContentControl设置
//通过接收JS传出消息的name进行捕捉的回调方法 js调OC
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSLog(@"name:%@\\n body:%@\\n frameInfo:%@\\n",message.name,message.body,message.frameInfo);
}
WKWebView的使用
WKWebView和UIWebView的区别
4.WKWebview Cookie
WKWebview Cookie 如何存储的
session级别的cookie
session级别的cookie是保存在WKProcessPool里的,每个WKWebView都可以关联一个WKProcessPool,如果需要在整个App生命周期内访问h5保留h5里的登录状态,可以将使用WKProcessPool的单列来共享登录状态
WKProcessPool是没有属性和方法的对象,唯一的作用就是标识是不是需要新的session级别的管理对象,一个实例代表一个对象
未过期的cookie
有有效期的 cookie 被持久化存储在 NSLibraryDirectory
目录下的 Cookies/
文件夹。
在Cookie目录下两个文件比较重要
Cookie.binarycookies
<appid>.binarycookies
两者的区别是<appid>.binarycookies是NSHTTPCookieStorag文件对象
Cookie.binarycookies是WKWebView实例化对象
这就是WKWebview 和 NSHTTPCookieStorage 的原因——因为被保存在不同的文件当中
WKWebview Cookie 如何工作的
1.当webView loadRequest或者302或者webView加载完毕,触发了ajax请求时,WKWebView所需的Cookie会去Cookie.binarycookies里读取本域名下的Cookie,加上WKProcessPool持有的Cookie一起作为request头里的Cookie数据
如何传递cookie
let cooki = "document.cookie = '这里是你需要的cookie值'
let userContentController = WKUserContentController()
let userScript = WKUserScript(source: cooki, injectionTime:WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
userContentController.addUserScript(userScript)
let config = WKWebViewConfiguration()
config.userContentController = userContentController
var url = URLRequest(url: URL(string: sqlUrl)!, cachePolicy: URLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 20)
webV = WKWebView(frame: UIScreen.main.bounds, configuration: config)
第一次拿到cookie
NSString *cookieStr = [self setupCookie]; //保持APP登录状态同步到web
WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:cookieStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[configuration.userContentController addUserScript:cookieScript];
- (NSString *)setupCookie
{ NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary];
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSString *currentHostUrl = [IQHAPIService apiBaseUrlString];;
NSString *hostDomin = [currentHostUrl stringByReplacingOccurrencesOfString:@"http://mobile" withString:@""];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
if ([hostDomin isEqualToString:cookie.domain]) {
[cookieDic setObject:cookie.value forKey:cookie.name];
}
}
NSString *sessionType = @"APPSESSIONID";
NSString *cookieStr = @"";
for (NSString *key in cookieDic) {
if([key isEqualToString:@"SESSION"]){
NSString *appendString = [NSString stringWithFormat:@"'%@=%@;path=/';",sessionType,[cookieDic valueForKey:key]];
cookieStr = [NSString stringWithFormat:@"%@document.cookie=%@",cookieStr,appendString];
}
}
return cookieStr;
}
5.远程推送原理
Provider是自己程序的后台服务器,APNS是Apple Push Notification Server的缩写,苹果推送服务器
分为三个阶段
1.应用程序的服务端把要发送的信息,目的iPhone的标识打包,发送给APNS
2.APNS在自身的已注册Push服务的iPhone列表中,查找相应标识的iPhone,并把消息发送到iPhone
3.iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知
APNS推送通知的详细工作流程
1.应用程序注册APNS消息推送
2.iOS从APNS获取deviceToken 应用程序接受deviceToken
3.应用程序将device token发送给程序的PUSH服务器程序
4.服务端程序向APNS服务发送消息
5.APNS服务奖消息发送给iPhone应用程序
由于直接生成的证书windows系统是不识别的,所以我们需要生成一个后缀为pem的带证书带秘钥的文件
1.把.cer的ssl证书转换为.pem文件
openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem
2.把私钥Push.p12证书转换为.pem文件
openssl pkcs12 -nocerts -out PushChatKey.pem -in Push.p12
3.把生成的两个pem文件再生成一个pem文件 把证书和私钥整合到一个文件里
cat PushChatCert.pem PushChatKey.pem > ck.pem
4.测试证书是否工作
telnet gateway.sandbox.push.apple.com 2195
5.使用SSL证书和私钥来设置一个安全的链接去链接苹果服务器
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem
6.建立推送
在AppDelegate里didFinishLaunchingWithOptions函数里写
(BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//推送的形式:标记,声音,提示
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
return YES;
}(void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
NSLog(@"regisger success:%@",pToken);
//注册成功,将deviceToken保存到应用服务器数据库中
}(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
// 处理推送消息
NSLog(@"userinfo:%@",userInfo);NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
}(void)application:(UIApplication *)applicationdidFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Registfail%@",error);
}
网友评论