您的位置:首页 > 其它

programming with oc回顾笔记

2015-09-11 17:15 246 查看
对于readwrite property, 如果getter setter都被重写了,则编译器不会自动生成 instance variable,得自己定义。对于readonly,getter被重写了也是同理。

正确的使用weak。
为了避免循环引用,会使用weak,但是weak的对象随时可能不在,那么如何处理呢。

如果是对weak发消息,那么什么也不会发生,没问题

如果讲weak对象作为参数传入,则要看该方法是否支持传入nil。例如 dictionary setObject就会出现异常导致崩溃。

如果一定要确保weak对象是存在的。那么就需要先用一个本地变量来强引用这个weak变量,官方的例子:

NSObject *cachedObject = self.someWeakProperty;           // 1
if (cachedObject) {                                       // 2
[someObject doSomethingImportantWith:cachedObject];   // 3
}                                                         // 4
cachedObject = nil;


在强引用之后,先判断对象是否存在,如果存在,那么之后使用这个对象一定是存在的。用完之后再nil,其实最后一步是不需要的,因为是方法体内的本地变量,作用域消失之后会自动nil。这种写法特别适合网络请求异步回调的block代码。

property如果是copy属性的,如果在初始化方法中赋值了对应的instance variable,则一定要使用copy方法。

- (id)initWithSomeOriginalString:(NSString *)aString {
self = [super init];
if (self) {
_instanceVariableForCopyProperty = [aString copy];
}
return self;
}


id<delegate>作为property,官方建议使用weak属性来避免循环引用。同理,在具体使用的时候,如果一定需要确保delegate存在,同样使用本地变量强引用之后再用。

代理的可选方法,定义者在向代理发消息之前要先检查是否代理实现了该方法。
之前接手一个项目,就遇到声明是optional,实际上却不做检查,我实现了代理的required部分,结果optional方法被强制调用,导致崩溃。

NSString *thisSegmentTitle;
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
}


fast enumeration with collection
enumeration的过程中,不可以修改collection,runtime会抛异常的。

for (id eachObject in array) {
NSLog(@"Object: %@", eachObject);
}


for (NSString *eachKey in dictionary) {
id object = dictionary[eachKey];
NSLog(@"Object: %@ for key: %@", object, eachKey);
}


block

如果定义了一个block变量,调用的时候如果变量是nil,会crash。到目前学习实践的项目暂时为用到将block作为property来传递的,觉得这样乖乖的。作为方法的参数感觉比较顺,在方法里面调用前先判断一下,如果block不是nil再调用。

如果作为property,官方建议添加copy属性,官方说ARC会自动做copy,为了看起来更清楚建议还是这样写。

block循环引用的问题
因为我们在block中大多数都会用到self,所以容易产生循环引用

如果block作为self的property,则铁定循环引用

如果block作为参数传递,例如网络异步请求的回调block,大多数self都是UIViewController,用block更新UI的,这个时候会产生一个现象,也就是由于block强引用了UIViewController,所以在网络请求没有结束之前,即使用户点了返回按钮,UIView在界面上不存在了,但是也不能被释放掉。所以也不能使用self.

__weak UIViewController * ws = self;

[function call: ....... completion: ^{
//如果后续逻辑不一定要求对象一定存在,则不需要这一步,大多数情况是不需要的。
__strong UIViewController sws = ws;
if (sws) { //如果一定要对象存在才能执行的逻辑 } }];


针对不同类型变量:

scalar variable:int ,float etc block是值COPY

Object-C object variable:

如果是local variable: 指针的值COPY,不会强引用self

如果是instance variable: 强引用self

如果是self.property,强引用self

@interface Sample()

@property (nonatomic) Date *dateVar;

@end
- (void)test {
NSDate *date = self.dataVar;

[function call:.... completion : ^{
[date timeIntervalSince1970]; //不会强引用self
[_dataVar timeIntervalSince1970]; //强引用self
[self.dataVar timeIntervalSince1970]; //强引用self;
}];
}


Name Convention
对于bool property,如果要兼容kvc,那么getter方法要修改为isXXX,除了bool property,其他类型的完全没有必要另外定义名字。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: