programming with oc回顾笔记

对于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,其他类型的完全没有必要另外定义名字。

 

posted @ 2015-09-11 17:15  怎么也得过啊  阅读(232)  评论(0编辑  收藏  举报