一、关键字说明
1、@synthesize:自动生成成员变量相应的存取方法,可以使用点语法操作该变量的存取。
2、@implementation: 表明类的实现 ,以@end 结束。
3、self :类似java语言当中的this ,是隐藏指针 指向接受消息的对象的指针 。消息所调用的方法使用该指针参数查找它要使用的实例。
4、super : 调用父类的方法 。 self = [ super init]; 判断是否可以成功初始化 如果父类成功初始化 那么将会赋值给 self ,这样self 是一个非空对象。 它不是参数也不是实例变量, 向super 发生消息的时候,实际上是在请求oc向该类的超类 发送请求 ,如果超类中没有定义的消息,oc将按照继承的普通规则在继承链中进行查找。
继承当中隐藏指针isa 与 super关键字 两张图片来演示:
5、#imoprt 与c语言当中的#include有类似的作用 ,告诉预处理器将头文件的内容包含到本文件的.oc中 ,并且保证头文件只会被包含一次 。
6、@interface 声明包含一个 XXX 类 ,与@implementation 一样 ,以@end结束。
7、: 表示继承 后面跟的是父类 。oc是单继承的机制 ,这里跟出c++是不一样的。
8、@property 关键字 设置成员变量的属性 (读/写 赋值 assign retain copy ,支持多线程的非原子访问nonatomic)
二、 方法的声明
1、 声明一个方法 格式是:
-(返回值)方法关键字 1 :(参数类型)参数名 方法关键字2 :(参数类型)参数名 …… (在读方法的时候 ,找方法关键字来确定参数)
2、-号是实例方法 +号是类方法
3、另一个初始化的方法中 调用 已有的初始化方法 这种方法被称为是 Designated initializer
三、输出流
NSlog是OC中的标准输出 ,附加输出 当时的时间 应用程序的名称 ,使用Nslog()输出任意对象的值时 都会使用%@格式说明 ,在使用这个说明符时 对象通过调用一个名为description的方法提供自己的NSlog()格式
四、getter / settter 方法
对象.属性:使用@property配合@synthesize 可以让编译器自动实现 getter/setter方法 ,很方便 可以直接使用”对象 属性“的方法调用
对象.方法:如果想要调用”对象.方法“的方式来调用一个方法并获取到方法的返回值 需要使用@property配合@dynamic 使用@dynamic 关键字是告诉编译器由我们自己来实现访问方法 。
五、属性的设置
1、readonly 此标记说明属性是只读的 ,默认的标记是读写 ,如果指定了制度 在@implementation中只需要一个读取器 或者你使用@synthesize关键字 ,也是有读取器方法被解析 而且如果试图使用点操作符 为 属性赋值 ,那么将会出现编译错误。
2、readwrite 此标记说明属性会被当成读写的 这也是默认的属性 设置器和读取器都需要在@implementation中实现 ,如果使用@synthesize关键字 读取器和设置器都会被解析
3、nonatomic 非原子性访问 对于属性赋值的时候不加锁 ,多线程并发访问会提高性能,如果不加此属性 则默认是两个访问方法都为原子型事务访问。
4、atomic 和 nonatomic用来决定编译器生成的getter和setter是否为原子操作 ,atomic 设置成员变量的@property属性时 默认为是atomic 提供线程安全 。在多线程环境下 ,原子操作是必要的 否则会引起错误的结果 。加了 atomic,setter函数会变成下面这样:
{lock}
if(property != newValue){
[property release];
property = [newValue retain];
}
{unlock}
nonatomic 禁止多线程,变量保护 提高性能 。atomic 是OC 使用的一种线程保护技术 ,基本上来讲 就是防止在 写 未完成的时候 被另外一个线程读取 ,造成数据错误。而这种机制是耗费系统资源的 ,所以在iPhone这种小型设备上 如果没有使用多线程间的通讯编程 那么 nonatomic是一个非常好的 选择。 访问器是原子操作 ,这也就是说 在多线程环境下,解析的访问器提供一个对属性的安全访问 ,从获取器得到的返回值或者通过设置器设置的值可以一次完成, 即便是别的线程也正在对其进行访问。 如果不指定nonatomic 在自己管理内存的环境中 ,解析的访问器保留并自动释放返回值 ,如果指定了 nonatomic ,那么访问器只是简单的返回这个值。
5、assign :简单赋值 ,不更改索引计数 ,适用于基础数据类型(NSInteger CGFloat)和C数据类型(int float double char 等)简单数据类型。 此标记说明设置器直接进行赋值 这也是默认值 。在使用垃圾收集的应用程序中,如果要一个属性使用assign ,且这个类符合NSCopying协议 你就要明确指出这个标记 而不是简单的使用默认值 否则的话,将会出现一个编译警告 ,这再次向编译器说明你确实需要赋值 即使它是可拷贝的。
6、copy :建立一个索引计数为1 的对象 然后释放旧对象 对NSString它指出 ,在赋值时使用传入值的一份拷贝 ,拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议的对象类型有效。
7、retain:释放旧对象 将旧对象的值赋予输入对象 ,再提高输入对象的索引计数为1,对其他NSObject和其子类 ,对参数进行release旧值 ,再retain新值,指定retain会在赋值时唤醒传入值的retain消息 此属性只能用于Objective-C对象类型,而不能用于Core Foundation 对象(原因是 retain会增加对象的引用计数 而基本数据类型或者 Core Foundation对象都没有引用计数)
注:把对象添加到数组中时 引用计数将增加对象的引用次数+1.
retain 的实际语法为:
-(void)setName:(NSString*)newName{
if(name != newName){
[name release];
name = [newName retain];// name's retain count has been retain 1
}
}
8、copy与retain
1.copy 其实是建立了一个相同的对象 ,而retain不是 比如说 个NSString对象 地址是0x1111 内容为@"STR" ,copy到另外一个NSString之后 ,地址为0x2222 内容相同 新的对象retain 为 1 ,旧有对象没 有变化 ; retain到另外一个NSString之后,地址相同(建立了一个指针,指针拷贝)内容当然相同 这个对象的retain值+1 也就是说 retain 是指针拷贝 copy 是内容拷贝。
2.retain的set方法是浅拷贝 copy的set方法是深拷贝
3.copy的另外一个用法:
copy是内容拷贝 对于像NSString的确是这样的 但是如果copy的对象是NSArray
比如:NSArray*array = [NSArray arrayWithObjects:@"hello",@"world",@"baby"];
NSArray*array2 = [array copy];
这个时候 系统的确是为array2 开辟了一块新的内存空间 但是 array2中的每个元素 只是copy了指向array中相对应元素的指针 这便是所谓的浅复制。
9、assign和retain
1.类似与C语言 当你malloc分配了一块内存 并且把它的地址赋给了指针a ,后来希望指针b也共享这一块内存 ,于是你又把a赋值给(assign)了b 。此时a和 b 指向同一块空间 ,当a不再需要这块内存的时候 ,能否直接释放它 答案是否定的 ,因为a并不知道b是否还在使用这块内存 ,如果a释放掉了这块内存 那么b在使用这块内存的时候 程序会crash掉
2.1当中assign出现的问题如何解决 最简单的方法就是使用引用计数 (reference counting),还是上面的哪个例子 我们给内存设一个引用计数 当内存被分配并赋值给a 的时候 引用计数是1, 当把a赋值给b的时候 引用计数为2 这时如果a不再使用这块内存 ,它只需要把引用计数减1 表明自己不再用于这块内存 。b不再使用这块内存的时候也把引用计数减1 当引用计数为0 的时候 ,代表该内存不再被任何指针指向 系统可以直接把它释放掉。
总结:上面两点就是assign和retain的区别 assign就是直接赋值 从而可能引起1.中的问题 当数据为int float等原生类型的时候,可以使用assign retain就如2.中所描述的问题一样 使用了引用计数 retain引起引用计数加1 release 引起引用计数减1 当引用计数为0的时候 dealloc函数被调用 内存被回收。
http://wenku.baidu.com/link?url=1Tla0N1G4bKsfwNjS6WUXsmDSI7JyzTM8b5TAMpHWpPxdWkqBls158651XysGzsr44Cue-0KcnybqXehLiKE9sZ8DRLuPJ3QQs85f67l9N7
内容节选自上述地址