1: objective-c与javascript交互
用 Objective-C 取得与设定 JavaScript 对象
1 | js: |
- JS 虽然是 OO,但是并没有 class,所以将 JS 对象传到 Obj C 程序里头,除了基本字串会转换成 NSString、基本数字会转成 NSNumber,像是 Array 等其他对象,在 Objective-C 中,都是 WebScriptObject 这个 Class。意思就是,JS 的 Array 不会帮你转换成 NSArray。
- 从 JS 里头传一个空对象给 Objective-C 程序,用的不是 Objective-C 里头原本表示「没有东西」的方式,像是 NULL、nil、NSNull 等,而是专属 WebKit 使用的 WebUndefined。
用 Objective C 调用 JavaScript function
- js调用oc
1 | oc: |
- oc调用js
1 | oc: |
DOM
- WebKit 里头,所有的 DOM 对象都继承自 DOMObject,DOMObject 又继承自 WebScriptObject,所以我们在取得了某个 DOM 对象之后,也可以从 Objective-C 程序中,要求这个 DOM 对象执行 JS 程序
1 | js: |
用 JavaScript 存取 Objective C 的 Value
要让网页中的 JS 程序可以调用 Objective-C 对象,方法是把某个 Objective-C 对象注册成 JS 中 window 对象的属性。之后,JS 便也可以调用这个对象的 method,也可以取得这个对象的各种 Value,只要是 KVC 可以取得的 Value,像是 NSString、NSNumber、NSDate、NSArray、NSDictionary、NSValue…等。JS 传 Array 到 Objective-C 时,还需要特别做些处理才能变成 NSArray,从 Obj C 传一个 NSArray 到 JS 时,会自动变成 JS Array。
首先我们要注意的是将 Objective-C 对象注册给 window 对象的时机,由于每次重新载入网页,window 对象的内容都会有所变动-毕竟每个网页都会有不同的 JS 程序,所以,我们需要在适当的时机做这件事情。我们首先要指定 WebView 的 frame loading delegate(用 setFrameLoadDelegate:),并且实作 webView:didClearWindowObject:forFrame:,WebView 只要更新了 windowScriptObject,就会调用这一段程序。
用 JavaScript 调用 Objective C method
- Objective-C 的语法沿袭自 SmallTalk,Objective-C 的 selector,与 JS 的 function 语法有相当的差异。WebKit 预设的实事是,如果我们要在 JS 调用 Objective-C selector,就是把所有的参数往后面摆,并且把所有的冒号改成底线,而原来 selector 如果有底线的话,又要另外处理。
2: jsbridge
OC端
- 引入依赖文件
1 | #import "WebViewJavascriptBridge.h" |
- 实例化一个对象
1 | self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView]; |
- OC端 注册一个方法+ 调用该方法的函数
1 | //供前端调用 |
JS端
1 | function setupWebViewJavascriptBridge(callback) { |
原理
- 分别在OC环境和javascript环境都保存一个bridge对象,里面维持着requestId,callbackId,以及每个id对应的具体实现。
- OC通过javascript环境的window.WebViewJavascriptBridge对象来找到具体的方法,然后执行。
- javascript通过改变iframe的src来出发webview的代理方法,从而实现把javascript消息发送给OC这个功能。
工作流
- JS 端加入 src 为 https://bridge_loaded 的 iframe
- Native 端检测到 Request,检测如果是 bridge_loaded 则通过当前的 WebView 组件注入 WebViewJavascriptBridge_JS 代码
- 注入代码成功之后会加入一个 messagingIframe,其 src 为 https://wvjb_queue_message
- 之后不论是 Native 端还是 JS 端都可以通过 registerHandler 方法注册一个两端约定好的 HandlerName 的处理,也都可以通过 callHandler 方法通过约定好的 HandlerName 调用另一端的处理(两端处理消息的实现逻辑对称)
3: ios本地缓存数据
直接写文件方式
- 可以存储的对象有NSString、NSArray、NSDictionary、NSData、NSNumber,数据全部存放在一个属性列表文件(*.plist文件)中。
NSUserDefaults
- 一般应用来存储应用设置信息,文件放在perference目录下。
归档操作(NSkeyedArchiver)
- 不同于前面两种,它可以把自定义对象存放在文件中。
coreData
- coreData是苹果官方iOS5之后推出的综合型数据库。
FMDB
- FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API,使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码。
4: 页面之间通信
- 属性传值
- 正向传值:page1–>page2
- 单例传值
1 | +(instancetype)sharedInstance{ |
- NSUserDefaults
- 代理传值
- A:代理方(遵守协议、实现协议方法)
- B:委托方(制定持有协议,调用协议方法)
- C:中间通讯(delegate)
- block传值
- 通知传值–NSNotificationCenter
1 | //先监听 |
5: 文件操作
- NSFileHandle:文件内容的读取和写入
- NSFileManager:文件的删除和创建等
- 参考
6: 多线程
PThread(c框架,极少使用)
NSThread
- 三种创建方式
1 | //方式一 |
GCD
介绍:
- 类似前端的new worker(), 把耗时较长的任务交给子线程处理,主线程处理ui操作,任务完成worker.postMessage()告诉给主线程。
使用方式:
- 同步/异步、串行/并行
- dispath_get_global_queue & dispatch_get_main_queue
- dispatch_group_async
- dispatch_once
- dispatch_after
NSOperation
实现方式:
- NSInvocationOperation & NSBlockOperation(同步阻塞)
- 自定义类继承NSOperation
相关概念
- NSOperationQueue(异步队列)
- addOperation
- setMaxConcurrentOperationCount
- 状态
- ready、 cancelled、 executing、 finished、 asynchronous
- 依赖– addDependency
- NSOperationQueue(异步队列)
NSRunloop阻塞当然线程,让异步到达同步的效果。
dispatch_semaphore(信号量)
1 | - (NSInteger)methodSync { |
7: @property使用
- 使用方式
1 | //test.h |
- 属性分类
- 原子性
- atomic (默认、原子性) 只有一个线程访问实例,atmoic是线程安全的。
- nonatomic (非原子性), 可以被多个线程访问,效率比atomic高,但是不能保证在多线程的安全性。
- 存取器控制
- readwrite (默认) 表示该属性同时拥有setter和getter。
- readonly 表示只有getter没有setter。
- 内存管理
- assign (默认) assign用于值类型,如int、float、double和NSInteger,CGFloat等表示单纯的复制。
- strong strong是在IOS引入ARC的时候引入的关键字,是retain的一个可选的替代。表示实例变量对传入的对象要有所有权关系,即强引用。strong跟retain的意思相同并产生相同的代码,但是语意上更好更能体现对象的关系。
- weak 在setter方法中,需要对传入的对象不进行引用计数加1的操作, 例如:IBOutlet、Delegate一般用的就是weak
- copy 与strong类似,但区别在于实例变量是对传入对象的副本拥有所有权,而非对象本身
- 原子性