IOS开发学习笔记(二十二)——ObjectC语言难以理解的概念汇总
2013-09-18 21:20
471 查看
这篇文章将会对ObjectC语言中比较难理解的概念进行汇总,帮助我们更好的进行iOS开发。
方法&成员变量&属性
我们首先看一个很简单的方法代码:
对于我这种用了多年C/C++和Java的程序员来说,实在比较难以理解,但是换个角度可以这样理解:
方法名称你可以认为是dequeueReusableCellWithIdentifier_forIndexPath;
参数有两个,第一个是NSString *类型,名字叫identifier;第二个是NSIndexPath *类型,名字叫indexPath;
最顶头的减号("-")标识是object方法,如果是加号("+")标识是静态(static)方法;
属性通过@private定义,并且需要你自己去显式通过实现方法来存取,或者.h文件中指定@property,.m文件中指定@synthesize来使得可以通过self.propertyName访问;
可以指定readonly指示符指示仅生成get方法;
注意对于静态方法(类方法)可以使用self或者super关键字指定使用自己还是父类的静态方法;
属性
对于属性中可能使用到的几个关键字我们这样理解:
nonatomic关键字说明这个是非原子操作的,所以可能是非线程安全的;
strong和weak关键字在所指定的属性是对象类型时使用。strong表示保持这个对象的指针所指向的内存,一直到使用结束;weak表示如果没有人再使用这个指针,那么就设置为nil;官方的解释是这样滴:
strong is the default. An object remains “alive” as long as there is a strong pointer to it.
weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.
另外还有一个比喻:
我们的属性可以认为是一条狗,他总是想逃跑;strong可以认为是狗链子,我们可以用多条链子拴住这条狗,只要有一条还抓在我们手里,狗就跑不了;而weak是一个看着狗的孩子,当链子在我们手中的时候,孩子可以看住狗,但是当链子不在我们手中时,狗就可以跑掉,尽管孩子在看着狗。
.h
注意obj2是strong还是weak对程序运行结果的影响。
.m
注意weak是在iOS5以后引入的,所以如果你的代码需要在iOS4上面运行,你只能使用strong。
上面讲得实际上就是引用计数的概念,strong类型的对象会被加上引用计数,当最后一个对象不再保留引用计数的时候,strong的对象就会被自动释放,所以这个时间点相对垃圾回收机制来说是可预期的;
局部变量由于在方法执行结束后超出其作用于,所以会被自动清除引用计数;
对于非ARC的程序,weak对应的关键字是unretain,strong对应的是retain关键字;另外还有一个关键字unsafe_unretain这个会造成野指针,不推荐使用,就不赘述了;
所有的属性,在你没有设置默认的setter的时候,初始化的值都是0;
可以使用if (obj)判断对象是否是nil,但一般情况下你无须这样去做。对一个nil的对象做一个操作(例如调用一个方法)将不会真正去执行这个方法,如果这个方法是有返回值的,一般都会返回0;但是如果这个方法是返回一个C类型的结构值的,那么你需要自己去事先检查这个对象是否是nil,因为无法保证返回的结构中的成员变量是有效的还是无效的,可能是一堆垃圾数据;
对于如何使用方法/成员变量/属性,建议采用如下规则:
所有的实例变量都声明为:@private;
所有属性都是用@property定义,并在方法中采用self.property或者super.property的方式引用;
.m文件中使用@synthesize使得编译器将setter和getter设置为与property同名的方法;
注意有这样的方法,可以强制你必须在代码中使用self.property的方式使用属性,在.m文件的interface段内这样写:
这样你在方法中必须使用self.myPrivateProperty这样的方式来引用成员变量。
注意在对象使用前最好检测是否是nil,因为对于object.property的使用形式,如果object本身是nil,并且property本身是一个CType的一个结构类型变量,那么property本身的值是未知的,可能会导致不可预知的错误;
对于需要打印输出的对象,可以重写-(NSString *)description方法(类似于java中的toString),并且可以在NSLog()中使用%@输出;
变量类型
对于变量类型有几个需要注意的地方:
Java中我们是可以定义一个String类型的变量(或者任意一个对象类型的变量),但在ObjectC中我们的对象必须使用指针类型定义:NSString *str;
id类型返回任意一个对象类型的变量,类似于Object。但注意:返回的仍然是一个指针,类似于NSString *;
事件响应方法:IBAction返回值类似于void;
注意BOOL类型的变量是YES/NO,不再是TRUE/FALSE;
访问控制符
访问控制符有几个需要注意的,我列举如下:
ObjectC的默认访问控制符是@protected的,当然你也可以定义为@private或者@public;
动态类型Dynamic Type
这里面最需要讨论的就是内省(Introspection):
isKindOfClass对于有java经验的我来说很好理解,可以理解为一个类是否是一个另一个类或其父类的实例;
isMemberOfClass就比较诡异了,是返回一个object是否这个类的实例,注意这里不检测继承关系,也就是说[teacher isMemberOfClass: [Teacher class]]返回YES,但是[teacher isMemberOfClass: [Person class]]返回NO。
注意看下面的代码:
ObjectC中有一种特殊的表达式:[tester respondsToSelector:@selector(test:)],其中的@selector是一个SEL类型,前面的表达式表示检查tester这个object有没有提供一个名字叫"test"的方法,注意表达式上"test"后面是有冒号的;
注意另一个问题,如果一个对象被设置为nil,那么以上的这些操作对于这个对象来说返回都是NO;
集合类型
集合类型使用的时候需要注意:
NSArray/NSDictionary/NSSet等都是不可变的集合类型,意思是在创建的时候就初始化内容,并且以后不可以再增加/删除内容;
NSMutableArray/NSMutableDictionary/NSMutableSet等是可变集合,分别类似于Java中的数组/Map等集合类型;
总体来说,ObjectC和C/C++/Java这些语言有类似的地方,但差异较大,过渡过来的学习曲线还是比较陡峭的,但只要抓住差异注意理解,上手还不是那么难,关键在于理解。
方法&成员变量&属性
我们首先看一个很简单的方法代码:
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
对于我这种用了多年C/C++和Java的程序员来说,实在比较难以理解,但是换个角度可以这样理解:
方法名称你可以认为是dequeueReusableCellWithIdentifier_forIndexPath;
参数有两个,第一个是NSString *类型,名字叫identifier;第二个是NSIndexPath *类型,名字叫indexPath;
最顶头的减号("-")标识是object方法,如果是加号("+")标识是静态(static)方法;
属性通过@private定义,并且需要你自己去显式通过实现方法来存取,或者.h文件中指定@property,.m文件中指定@synthesize来使得可以通过self.propertyName访问;
可以指定readonly指示符指示仅生成get方法;
注意对于静态方法(类方法)可以使用self或者super关键字指定使用自己还是父类的静态方法;
属性
对于属性中可能使用到的几个关键字我们这样理解:
nonatomic关键字说明这个是非原子操作的,所以可能是非线程安全的;
strong和weak关键字在所指定的属性是对象类型时使用。strong表示保持这个对象的指针所指向的内存,一直到使用结束;weak表示如果没有人再使用这个指针,那么就设置为nil;官方的解释是这样滴:
strong is the default. An object remains “alive” as long as there is a strong pointer to it.
weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.
另外还有一个比喻:
我们的属性可以认为是一条狗,他总是想逃跑;strong可以认为是狗链子,我们可以用多条链子拴住这条狗,只要有一条还抓在我们手里,狗就跑不了;而weak是一个看着狗的孩子,当链子在我们手中的时候,孩子可以看住狗,但是当链子不在我们手中时,狗就可以跑掉,尽管孩子在看着狗。
.h
@interface ViewController : UIViewController @property (nonatomic, strong) MyType *obj1; @property (nonatomic, weak) MyType *obj2; @end
注意obj2是strong还是weak对程序运行结果的影响。
.m
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. obj1 = [[MyType alloc] init]; obj2 = obj1; obj1 = nil; NSLog(@"obj2 = %@", obj2); }
注意weak是在iOS5以后引入的,所以如果你的代码需要在iOS4上面运行,你只能使用strong。
上面讲得实际上就是引用计数的概念,strong类型的对象会被加上引用计数,当最后一个对象不再保留引用计数的时候,strong的对象就会被自动释放,所以这个时间点相对垃圾回收机制来说是可预期的;
局部变量由于在方法执行结束后超出其作用于,所以会被自动清除引用计数;
对于非ARC的程序,weak对应的关键字是unretain,strong对应的是retain关键字;另外还有一个关键字unsafe_unretain这个会造成野指针,不推荐使用,就不赘述了;
所有的属性,在你没有设置默认的setter的时候,初始化的值都是0;
可以使用if (obj)判断对象是否是nil,但一般情况下你无须这样去做。对一个nil的对象做一个操作(例如调用一个方法)将不会真正去执行这个方法,如果这个方法是有返回值的,一般都会返回0;但是如果这个方法是返回一个C类型的结构值的,那么你需要自己去事先检查这个对象是否是nil,因为无法保证返回的结构中的成员变量是有效的还是无效的,可能是一堆垃圾数据;
对于如何使用方法/成员变量/属性,建议采用如下规则:
所有的实例变量都声明为:@private;
所有属性都是用@property定义,并在方法中采用self.property或者super.property的方式引用;
.m文件中使用@synthesize使得编译器将setter和getter设置为与property同名的方法;
注意有这样的方法,可以强制你必须在代码中使用self.property的方式使用属性,在.m文件的interface段内这样写:
@interface MyViewController () @property int myPriveteProperty; @end
这样你在方法中必须使用self.myPrivateProperty这样的方式来引用成员变量。
注意在对象使用前最好检测是否是nil,因为对于object.property的使用形式,如果object本身是nil,并且property本身是一个CType的一个结构类型变量,那么property本身的值是未知的,可能会导致不可预知的错误;
对于需要打印输出的对象,可以重写-(NSString *)description方法(类似于java中的toString),并且可以在NSLog()中使用%@输出;
变量类型
对于变量类型有几个需要注意的地方:
Java中我们是可以定义一个String类型的变量(或者任意一个对象类型的变量),但在ObjectC中我们的对象必须使用指针类型定义:NSString *str;
id类型返回任意一个对象类型的变量,类似于Object。但注意:返回的仍然是一个指针,类似于NSString *;
事件响应方法:IBAction返回值类似于void;
注意BOOL类型的变量是YES/NO,不再是TRUE/FALSE;
访问控制符
访问控制符有几个需要注意的,我列举如下:
ObjectC的默认访问控制符是@protected的,当然你也可以定义为@private或者@public;
动态类型Dynamic Type
这里面最需要讨论的就是内省(Introspection):
isKindOfClass对于有java经验的我来说很好理解,可以理解为一个类是否是一个另一个类或其父类的实例;
isMemberOfClass就比较诡异了,是返回一个object是否这个类的实例,注意这里不检测继承关系,也就是说[teacher isMemberOfClass: [Teacher class]]返回YES,但是[teacher isMemberOfClass: [Person class]]返回NO。
注意看下面的代码:
obj1 = [[MyType alloc] init]; NSLog(@"obj1 isKindOfClass:NSObject = %@", ([obj1 isKindOfClass:[NSObject class]]) ? @"YES" : @"NO"); NSLog(@"obj1 isMemberOfClass:NSObject = %@", ([obj1 isMemberOfClass:[NSObject class]]) ? @"YES" : @"NO"); NSLog(@"obj1 isMemberOfClass:MyType = %@", ([obj1 isMemberOfClass:[MyType class]]) ? @"YES" : @"NO");
ObjectC中有一种特殊的表达式:[tester respondsToSelector:@selector(test:)],其中的@selector是一个SEL类型,前面的表达式表示检查tester这个object有没有提供一个名字叫"test"的方法,注意表达式上"test"后面是有冒号的;
注意另一个问题,如果一个对象被设置为nil,那么以上的这些操作对于这个对象来说返回都是NO;
集合类型
集合类型使用的时候需要注意:
NSArray/NSDictionary/NSSet等都是不可变的集合类型,意思是在创建的时候就初始化内容,并且以后不可以再增加/删除内容;
NSMutableArray/NSMutableDictionary/NSMutableSet等是可变集合,分别类似于Java中的数组/Map等集合类型;
总体来说,ObjectC和C/C++/Java这些语言有类似的地方,但差异较大,过渡过来的学习曲线还是比较陡峭的,但只要抓住差异注意理解,上手还不是那么难,关键在于理解。
相关文章推荐
- IOS开发学习笔记(一)——ObjectC语言快速入门
- objectc学习笔记----《马上着手开发 iOS 应用程序 (Start Developing iOS Apps Today)》
- ios开发学习笔记001-C语言基础知识
- IOS开发学习笔记(十一)——ObjectC中集合类型的使用
- iOS开发笔记--iOS项目中工作空间Workspaces概念的理解
- IOS开发学习笔记(十二)——ObjectC中的复杂类型
- IOS开发学习笔记-(2)键盘控制,键盘类型设置,alert 对话框
- iOS开发笔记——关于Assets.xcassets的学习
- 移动开发:iOS学习之 编译错误汇总
- ios学习笔记(一)Windows7上使用VMWare搭建iPhone开发环境
- IOS学习笔记(十二)之IOS开发之表视图(UITableView)的相关类,属性与表视图实现学习(二)
- IOS开发学习笔记035-UIScrollView-自动滚动
- 2011斯坦福大学iOS应用开发教程学习笔记
- UML 学习笔记------ 面向对象概念的理解
- IOS开发学习笔记(十三)——创建日历事件
- iOS开发学习笔记-C语言学习(六)
- iOS开发学习笔记 1-0 开篇
- IOS学习笔记--IOS常用控件汇总
- IOS开发学习笔记(二)——简单小例子
- 2011斯坦福大学iOS应用开发教程学习笔记(第二课)My First iOS App