乐趣区

iOS知识梳理-关于ObjectiveC

作为早期的面向对象语言,且直到现在仍然为人们所熟知,Objective- C 显然有其独到之处。
这里对 Objective- C 的特点进行简单阐述。

动态?静态?

Objc 这个语言具有比较强大的动态特性,常提到的包括动态类型、动态绑定、动态加载。
动态类型主要指类指针 id,其类型是在运行时才能决定的。
动态绑定指一个对象的方法可以在运行时添加、替换。
动态加载指运行时可以动态地创建新的类。
因此我们称 Objc 是一个动态类型的动态语言。

虽然 Objc 有着诸多动态特性,但它并不是个像 JavaScript、python 那样典型的动态语言,有的人会说 Objc 是个“动静结合”的语言。它虽然有动态类型,但是更常用的是静态类型系统;而动态加载、动态绑定更是高级特性而非基本语法。

总的而言,Objc 写起来更像静态语言的感觉(啰嗦),但它有着丰富的动态特性。

消息传递 vs 函数调用

对象间的通信形式应当是怎样的?
函数调用的方式是指,调用方直接或间接地拿到被调用方的函数地址进行函数调用。
而消息传递是指,调用方只是把方法名和参数等信息传递给被调用方,具体的执行由被调用方处理。

显然,消息机制会更加灵活。
早年的半篇神作 function/bind 的救赎(上)中大佬对消息传递和方法调用的区别做了深刻分析,阐述了消息机制的优点,值得一读。不过作者可能把调用机制看得太重了。

内存管理

内存管理大体上有三类,开发者手动维护、基于引用计数并提供一些机制解决循环引用、自动垃圾收集。
自己手动派主要就是 c /c++ 了,性能最好,缺点是开发者心智负担重。
垃圾回收派是最多的,现在流行的语言大多都是 gc 的路子,Java/JavaScript/python/golang 等等。优点是轻松,缺点是通常情况下 gc 是阻塞的,触发 gc 时会有几十 ms 到数百 ms 的卡顿。现在也有并发 gc 的技术,不过用得并不广泛,不太了解。
Objc 属于基于引用计数并提供一些机制解决循环引用的。我们知道,朴素的引用计数存在的问题是无法识别循环引用。Objc 提供了 ARC 机制,开发者标记对象间的引用是强引用还是弱引用,Objc 的 runtime 来解决剩下的事情。使得内存管理的性能和开发者的负担得到了比较好的平衡。同属这一流派的还有个 Rust 的所有权机制。

方法定义和方法调用的语法

这个点只是个小细节了,跟上面的不在一个层面,不过这可能是大部分人初学 Objc 时觉得跟其它语言最大的不同。

Objc 的方法声明是这个样子的:

- (void)insertString:(NSString *)aString atIndex:(NSUInteger)loc;

它包含了方法标示符 (-)、返回类型(void)、方法名称(insertString:atIndex:)、参数类型和参数名称。注意,每个参数前面那一两个次的描述,是算在函数名里面的。
其实回头看来,这样的语法是有一定优点的。
前两天看一个 c ++ 的库,里面有个函数有 12 个参数,调用的时候就很烦,总担心我填的参数错位了:

demoFunc(var1,var2,var3,var4,var5,var6,var7,var8,var9,var10,var11,var12)

Objc 虽然啰嗦了点,但是看起来其实会比较清晰,比如一个很长的方法:

- (id)initWithBitmapDataPlanes:(unsigned char **)planes 
                    pixelsWide:(NSInteger)width 
                    pixelsHigh:(NSInteger)height 
                 bitsPerSample:(NSInteger)bps 
               samplesPerPixel:(NSInteger)spp 
                      hasAlpha:(BOOL)alpha 
                      isPlanar:(BOOL)isPlanar 
                colorSpaceName:(NSString *)colorSpaceName 
                  bitmapFormat:(NSBitmapFormat)bitmapFormat 
                   bytesPerRow:(NSInteger)rowBytes 
                  bitsPerPixel:(NSInteger)pixelBits;

调用时是这个样子:

NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
                            initWithBitmapDataPlanes:(unsigned char **)&data
                            pixelsWide:gWidth
                            pixelsHigh:gHeight
                            bitsPerSample:8
                            samplesPerPixel:3
                            hasAlpha:NO
                            isPlanar:NO
                            colorSpaceName:NSCalibratedRGBColorSpace
                            bytesPerRow:gWidth*3
                            bitsPerPixel:24];

每个参数是啥会比较明确。

退出移动版