读《iOS进阶开发》笔记
自我技术的提高,是可以通过阅读技术博客,图书,苹果官方WWDC视频来提高。
而就个人环境而言,我们可以多与同行进行交流,关注行业动态,新技术的发展方向。
其实就是多写代码 多思考。
工具篇
源码管理工具 CocoaPods
正如Java的源码管理工具是Maven,nodejs的npm。其实绝大部分的iOS开发工程师都使用过CocoaPods这个工具,只需要建立一个Podfile,在里面编辑上需要的第三方库名称,执行pod install就可以把网路第三方库拉到自己的工程中。
网络抓包工具 Charles
以前做硬件上的抓包是使用WireShare,现在需要在iOS抓包则可以使用Charles(小名 青花瓷),使用也很简单。
- 保证自己的设备和mac在同一网段。
- 设置设备的代理,端口为8888。
- 在mac上打开Charles的代理模式,就可以抓取设备的网络请求了。
除此之外Charles还可以模拟慢速网络,网络转发,response的修改等等,总的来说就是功能很强大的网络调试工具。
界面调试工具 Reveal
这个比较少用,因为Xcode上有快捷的视图调试。不过之前试用过感觉功能还是很多的。
移动统计工具 Flurry
Flurry主要是为了移动应用提供数据统计和分析,能够很方便的统计应用的使用情况,如时间段内的用户使用次数,新增的用户数,活跃用户数,移动设备分类情况等。除了这些,还能支持自定义的统计项,如网络请求时间,按钮点击次数等。
使用起来也很简单,注册账号-下载sdk-对照着文档就可以开始你的统计。
崩溃日志记录工具 Crashlytics
每天都会把App的崩溃信息,统计发送到你的邮箱(这点很贴心)。除了崩溃信息,还会把崩溃设备的版本号,内存量,是否越狱等信息一并发送,这对于我们定位bug来说是很有用处的。
其它的插件 (自己使用的)
- Alcatraz Xcode插件管理工具
- VVDocumenter 文档神器
- SwiftCodeSnippets Swift语法块
实践篇
引用计数 && GCD && UIWindow
- 引用计数这章就是表示iOS的内存是怎样管理的,从原理上说了我们为什么会有循环引用,怎样避免循环引用(恰当用weak 或者 unowned 引用变量)
- GCD 可以参考我之前写的那一篇
- UIWindow的使用场景就是 需要把某个视图置于最上层,但不要滥用,要处理好模块之间的耦合关系
动态下载中文字体 && 应用内支付
这两个都用得比较少,主要是因为字体的话可能一开始就导到工程里面去了,而支付的话一般都是使用ping++
- 动态下载系统字体是存在系统的目录下的,不会造成应用体积的增加
- nil
基于UIWebView的混合编程
关键是OC与js之间的交互。
- OC调用js是通过UIWebView的
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
方法实现的,调用这个方法能够向UIWebView传递一段需要执行的js文本,最后获得执行结果。 - 而js调用OC语言,是通过一种”曲线救国“的方法,主要是利用了UIWebView的特性 在UIWebView内的所用网络请求,都可以通过UIWebViewDelegate截获到,而js的请求加载内容通常都不是真实的地址,地址通常都是以
gap://
开头的。我们只需要每次判断请求的头部字符串就可以进行我们自己应用的调用逻辑。 - 如何传递参数
参数传递最简单的方式是将参数作为 URL 的一部分,放到 iFrame 的 src 里面。这样 UIWebView 通过截取分析 URL 后面的内容即可获得参数。但是这样的问题是,该方法只能 传递简单的参数信息,如果参数是一个很复杂的对象,那么这个 URL 的编码将会很复杂。 对此,有道云笔记和 Cordova 采用了不同的技术方案。
• 书中的技术方案是将参数以 JSON 的形式传递,但是因为要附加在 URL 之后,所以我们 将 JSON 进行了 Base64 编码,以保证 URL 中不会出现一些非法的字符。
• Cordova 的技术方案,也是用 JSON 传递参数,但是将 JSON 放在 UIWebView 中的一个全 局数组中,当 UIWebView 需要读取参数时,通过读取这个全局数组来获得相应的参数。
安全性问题
账户登陆正确的网络请求做法:事先生成一对用于加密的公私钥,使用公钥加密,传输到服务器之后,服务器使用私钥解密,然后加盐
Salt:指的是在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符
再多次求MD5,之后再和服务器原来存储的用同样方法处理的密码匹配,如果一致,则登陆成功。
CoreText
CoreText是用于处理iOS文字排版的底层技术。这个技术通常是用来处理文字/图片的混排,相应某些字符串片段的点击事件,用于自定义文本引擎。与UIWebView相比较下,CoreText有着处理速度更快,更细腻,交互效果更好的优势。
在书中作者向我们展现了如何写一个简单的图文混排引擎,github地址在这里
实战技巧
列举了很多技巧,这里写一些我觉得我能用得上的。
- 快速把应用下架的方法:把上架时间改成未来的一个时间
- NSJSONSerialization 比 NSKeyedArchiver 更好 :网上测试
- 设置应用内的系统控件语言:
<key>CFBundleLocalizations</key>
<array>
<string>zh_CN</string>
<string>en</string>
</array>
-
清除DerivedData: 当多次重构工程造成代码没有错却编译失败时,可以尝试删除 DerivedData 目录。DerivedData
目录是 Xcode 的编译缓存, 路径是~/Library/Developer/Xcode/DerivedData
-
给模拟器相册增加图片: 测试需要图片,但模拟器的相册是空的怎么办?可以把图片从 Finder 中拖动到模拟器中。可以用Safari打开这张图,然后长按这张图,在弹出的菜单中选择“Save Image”,就可以把图 片保存到模拟器的相册中了。
iOS开发底层原理
Objective-C对象模型
nil
Method Swizzling
这个是属于iOS黑魔法的一种,不仅在OC能用,在Swift也可以使用,Swift的用法戳这里
Tagged Pointer对象
Tagged Pointer对象的推出时为了适应64位架构的处理器,能够节省内存和提高执行的效率。
在64位系统上,假如我们需要存储一个NSNumber对象,占用的内存是与CPU的位数有关的,在32位CPU下占4个字节,在64位CPU下则是占8个字节,而指针所占的内存也是与CPU位数成正相关的。
在这种情况下,苹果推出了Tagged Pointer,是为了更优化内存的使用效率,一种优化的数据结构。具体体现在将一个对象的指针拆分两部分,一部分直接保存数据,另一部分则作为特殊标记,表示这是一个特别指针,不指向任何一个地址,如果数据的确需要占用到该类型的整个内存时,Tagged Pointer则失效,并以普通对象的方式保存。
64位下的isa指针优化
对于普通的对象,isa指针也通过Tagged pointer对象进行了优化,主要体现在对isa指针部分未用到的位数(31位)进行标识,进而简化了对对象引用计算的计算过程(主要是免除了在32位下的全局加锁操作)。
如,Retain操作如下:
- 检查isa指针上面的标记位,看引用计数是否存在isa变量中,如果不是,则使用以前的步骤,否则则行第2步
- 检查当前对象是否正在释放,如果是,则不做任何事情
- 增加该对象的引用计数,但是并不马上写会isa变量中
- 检查增加后的引用计数的值是否能够被19位表示,如果不行,则切换回以前的办法,否则执行第5步
- 进行一个原子的写操作,将isa值写回
block的内部数据结构定义
在MRC模式下,block具体分为这三种类型:
- _NSConcreteGlobalBlock, 全局的静态block,不会访问任何外部变量
- _NSConcreteStackBlock, 保存在栈中的block,当函数返回时会被销毁
- _NSConcreteMallocBlock, 保存在队中的block,当引用计数为0时会被销毁
特别地,在MRC模式下,_NSConcreteMallocBlock类型的block并不会在源码中直接出现,因为默认它是当一个被copy的时候,才会将这个block复制到堆中。
在ARC模式下,block类型会受到影响,具体表现在只会有_NSConcreteGlobalBlock 和 _NSConcreteMallocBlock类型的block
看完书,简单记录一下。