代码改变世界

Objective-C 一些很基础的总结

2012-01-12 17:32  curer  阅读(3193)  评论(5编辑  收藏

学习 Objective-C大概4个月了,居然给一个还没毕业的家伙吹了吹,呼,希望不要误人子弟。这里总结一下,毕竟这是第一次完整的讲一个东西。

附上PPTObjective-C Primary 。资源99%来自WWDC 2010 session 113。

Common Concepts

Objective-C 相对其他更了解的C++语言来说,还是有些不同的。如下表

 

image

这里面有几点比较重要

  1. Objective-C 中所有的类,其实是另一种“类”的对象,所以Objective-C 中的类方法,其实是另一种类的实例方法。 Objective-C Message
  2. Objective-C 中没有静态变量,都是用全局变量实现的。

Category

如何给一个类增加一个函数方法,在C++中是不可能的(或是很难)但是在Objective-C中确实很简单的事情,category 做的就是这件事情。

当第一次看到category 时,我几乎肯定这是一个非常坑爹的设计,因为这个可以完美的覆盖原有类的方法,如果使用不当,绝对是灾难性的错误。但是,随着使用时间变长category 的好处也慢慢体会出来。

  • 给系统原有的类或是第三方的类增加函数,而不用使用一个新的类,这样使用会更加方便,特别是使用IB时,不需要将系统的类换成自己定义的类,这样减少了非常多的移植问题和同步工作。

当然,如果使用不当,也会遇到问题

  • 函数覆盖问题,之前提到过
  • 增加大量的category 会降低系统性能,特别是如果大量的加到一些基础类上,如NSObject 等,因为,几乎整个系统都在使用这些类,而过多的category,不仅降低自己代码的效率,也会降低framework代码的效率,这里的效率,应该主要在类初始化上,和消息发送上面。

SEL

Memory Management

语言是离不开平台的,而内存管理,则是了解平台中最基础的部分。而cocoa touch 的内存设计也就是基于引用计数的设计,是针对很早以前的设备设计,显然不适合现在的硬件设备。但是,现在我们似乎没有其他的选择,在一开始学习时。

基于引用计数的内存管理,设计的本质其实就是一个Directed Acyclic Graph(有向无回图)

image

对于引用计数的内存管理,这一点实在是不陌生,不管是什么语言,都会遇到一个问题,循环引用

image

当形成回路时,循环引用发生,导致内存泄露。而对应的方法,不管是什么语言,都需要把引用分为强引用和弱引用

image

解决引用循环的方法很多,但是实质上,都是通过抽象成父子关系来做,一个强引用,一个弱引用,图形下方的节点通过弱引用连接上面的节点,图形上方的节点,通过强引用连接下方节点。实例就是delegate,属性被声明为assign

Autorelease Pools

autorelease 应该是初学者最容易糊涂的地方,一开始我也非常害怕使用Autorelease 变量,因为,这些变量不仅会增大内存开销,而且使用不当,crash的位置就是main函数,调试器几乎没有任何帮助,但是仍然有非常多的framework是基于autorelease 变量的,所以还是需要屡屡。

cocoa touch 是事件驱动的,我们通过接受一个个的event来跑我们的程序,那么简单的讲,就是一个while的死循环,不断地获取一个event,处理一个event。

image

处理event的时候,framework 帮我们建立了一个autorelease pool。

image

当我们处理或是叫响应一个event时,比如调用了[NSDate date] 函数,这个函数,返回了一个autorelease 变量d

而这个变量,事实上是被autorelease pool 所引用。

image

当一层层stack pop 之后,我们可以看到 autorelease 变量的生命周期

image

image

当调用[pool drain]后,autorelease pool 随之消失,伴随着还有那个var d,回到原点,在下一个event cycle

image