iOS学习开发iOS 杂货铺

再读Effective Objective-C 2.0

2019-04-12  本文已影响19人  StrongX

第一次阅读《Effective Objective-C 2.0》这本书是在15年,这些年过去回过头去看,当年那些经验还是一点都不过时,有些细节点还是值得反复强调。我在这里列举一些大家可能平时不大会留意的地方。
-- 2019-04-12 00:39 来自StrongX的博客

image.png

通过上图我们知道OC变量指针保存在栈中,而实际内容则是保存在堆中,这里我们就需要注意悬挂指针的产生,悬挂指针难以调试,而且经常造成的现象就是一会取值正确,一会取值不正确。这是由于堆中的内容已经被标记为释放,而实际上内存并没有被释放,能否正确取到值取决于这一片内存是否被重写,产生悬挂指针是非常危险的。


而实际上我在之前老的项目的确见到过没有遵循这一准则的情况,没有同时使用staticconst同时来修饰一个变量,而仅仅使用了const来做修饰。如果不使用static来修饰变量,那么编译器就会对此变量添加一个“外部符号”。那么此时你如果同时在两个文件中定义了相同的变量名,那么编译器就会报错:

ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

当然编译器会告诉在哪些文件中那个变量发生了重复定义。所以我们在定义常量的时候一定要同时使用staticconst来进行定义,因为发生重名情况并不罕见。


我们经常有这样的场景:我们需要提供变量对外可读,但是在类实现中可以去修改,所以我们在 .h文件中定义变量为readonly

@property (nonatomic, strong,readonly) NSString *name;

然而这个时候我们无法.m文件中进行修改,当你试图去修改一个由readonly定义的变量时,编译器会发出错误:

Assignment to readonly property

那么这个时候我们可以在分类中同时将变量定义为readwrite(不了解分类概念的同学,可以自行去了解下)

@property (nonatomic, strong, readwrite) NSString *name;

id maybeAnArray = /* ... */;
if ([maybeAnArray class] == [NSArray class]) {
  // Will never be hit
}


image.png

上面这段代码完美解决了由于计时器持有selfself又持有计时器而导致计时器若是不销毁就会发生内存泄漏的问题,计时器不再持有self,在iOS 10以后NSTimer开放给我们的接口中出现了这么一个方法:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block;

使用此方法创建的计时器同样不会造成“保留环”,估计实现方式和上面贴的那段代码估计原理是类似的。


先写这么多,下回再写,晚安。

上一篇 下一篇

猜你喜欢

热点阅读