类定义相关:
@property
- 为一个类的成员变量设置相关的属性。通过property定义的变量,编译器会自动写出一套存储方法,用以访问给定类型中具有给定名称的变量。例如:
- 定义变量:@property (nonatomic, copy) NSString *name;
- 若是在.m文件中没有用@dynamic关键字重新标识,则编译器会自动生成它的getter(-(NSString *)name)和setter(-(void)setName:(NSString *)name)方法。
atomic & nonatomic
- atomic:默认设置。保证在多线程的情况下定义变量or对象的原子性,即编译器会自动生成一些互斥锁的代码。
- nonatomic:若无需保证对象or变量的原子性,可以设置该属性,减少编译器的附加代码(互斥锁)生成。
读写权限
- readwrite:默认设置,编译器会自动生成存储器,即属性拥有获取方法(getter)和设置方法(setter),在新版本的xcode5中已经不需要用@synthesize实现就能够自动生成存储方法了。
- readonly:编译器只生成getter方法,不会生成setter方法。可以在头文件中对变量定义成readonly,在.m文件中重新定义其的读写属性,如此可以保证对外是只读的。
内存管理语义
- strong:强引用,其存亡直接决定了所指向对象的存亡。若该对象不存在指向它的引用,并且对象不再显示在对象列表中,则该对象会从内存中释放。
- 具体体现为:当设置新值时,先保留新值,并释放旧值,然后再将新值设置上去。
- weak:弱引用,不决定对象的存亡。即使一个对象被若引用了很多次,只要没有强引用指向它,它还是会被释放。
- 具体体现为:当设置新值时,既不保留新值,也不释放旧值,与assign较为类似。当属性所指的对象被销毁时,属性值也会清空。
- assign:默认类型,setter方法直接赋值,不进行任何的retain操作,也不改变引用计数,通常用于处理基本数据类型。
- 只针对“纯类型”(例如:CGFloat,NSInteger等)的简单赋值操作
- unsafe_unretained:语义与assign相同,它适用于“对象类型”,表达一种“非拥有关系”。
- 具体体现为:不保留新值和旧值,当目标对象遭到销毁时,属性值也不会自动清空(不安全:unsafe),这一点与weak有区别。
- copy:与strong类似。然后它不保留新值,而是将其拷贝。
- 释放旧对象,再复制新对象,将retainCount设置为1。copy是为了减少上下文依赖而引入的机制。注意,使用copy属性,需要符合NSCopying协议,即必须实现-(id)copyWithZone:(NSZone *)zone
- retain:释放旧对象,将旧对象的值赋值给新对象,再令新对象的引用计数+1。
方法名
- getter=<name>:指定获取方法的名称。
- 例如:@property (nonatomic, getter=isEmpty) BOOL empty;
- setter=<name>:指定设置方法的名称,此方法一般不太常见。
- 通过上述特质,可以微调由编译器合成的存储方法。不过需要注意:若是自己来实现存储方法,应该保证其具备相关属性所申明的特质。
@interface
Objective-C类的定义:
- @interface ClassName
Category定义:
- @interface ClassName (category name)
- category是iOS的一种设计模式,用于向已经存在的类添加方法从而达到扩展已有类的目的。简单来说,可以在不修改原有类的情况下,为该类扩展新的方法。在大多数情况下,使用category方式比创建子类更好。在category中新添加的方法也会被扩展类的子类自动继承。例如:当已知类A中某方法存在一个BUG,但该类以类库的形式存在,我们无法修改源码。此时,Category可以用于替代这个已有类中的某个方法的实体,从而到达修复BUG的目的。【注】用category来替换某一个方法的时候,要注意实现原方法中的功能。与子类不同的时,category不能用于向被扩展类中添加实例变量。category通常作为一种组织框架代码的工具来使用。
- category的用途:
- 在不创建子类的情况下实现对原有类的扩展
- 简化类的开发工作(当一个类需要多个程序员协同开发的时候,category可以将同一个类根据用途分别放在不同的原文件中,从而便于程序员独立开发相应的方法集合)
- 将常用的相关方法分组
Objective-C扩展:
- @interface className ()
- 是一种特殊的category,能够增加成员变量。一般在类的源文件中使用,定义私有属性和方法。
包含引用相关
@class
- 告诉编译器这个类存在,但是类如何实现的不用告诉编译器。当我们在一个文件中需要使用一个类来定义对象,但又不想包含该类的头文件,只需要通过@class关键字申明该类的名称,表示该类存在即可。
#include
- <……>引用系统文件,编译器会在系统文件目录下查找该文件;"……"用户自定义文件的引用,编译器会先去用户目录下查找,然后去安装目录,最后去系统目录。
#import
- 引用一个文件或模块,与#include类似。相较于#include而言,避免了重复引用的问题。
@import
是iOS7的一个新特性,成为模块引用或语义包含。他是对预编译头文件的一种更好的使用方法,通过@import能够使用iOS7和系统中任何frameworks的模块。它们打包成了一个可执行的framework,据说相较于#import而言更加有效和安全。
优势:
1. 使用@import来包含一个模块可以不必在project settings中添加framework,系统会自动加载framework。2. 不必直接使用@import关键字,所有的#import和#include指令都自动映射成了@import。这意味着,不需要改变源码。
官方优势:
1. 包含了framework的完整语义描述2. 不需要解析头文件3. 更好的包含framework的接口4. 加载二进制的现实5. 比预编译头文件更灵活6. 忽略本地宏定义的影响7. 新工程的默认使能。
类实现相关
@implemetation
- 实现一个Objective-C的类,类的名称需要与@interface定义的Objective-C的类一致。需要以@end结束类的实现。
@synthesize
- 在ios6之前,该@synthesize与@property协同使用,完成对属性的使用,否则属性不可用。使用@synthesize之后,编译器会自动生成setter和getter方法。
@dynamic
- 与@synthesize类似,不同的是用dynamic修饰的属性,其setter和getter方法会在程序运行时或其他方法进行绑定,以便让编译器通过编译。其主要用在NSManagerObject对象的属性申明上,由于该对象的属性一般是从Core Data的属性中生成的,会在程序运行时为此类的属性生成setter和getter方法。
协议相关
@protocal
- 定义一个协议。是一系列方法的集合,分成强制和非强制两部分。当要实现一个协议时,必须要实现所有的强制方法,非强制方法可以根据实际情况来实现。protocal可以继承,在类申明中用<>说明。一个类可以继承多个协议。
@required
- 对方法属性的设定,表示必须要实现的方法。
@optional
- 对方法属性的设定,表示可选择要实现的方法。
其他关键字
IBOutlet
- 如果界面是通过xib绘制的,需要在实例变量申明时用这个关键字,表示对象在interface builder中创建。一旦创建的对象连接到该接口,就可以像访问任何对象一样访问它。
- 在interface builder中使用特殊的初始化方法initWithCoder:进行手动创建对象。
IBAction
- IBAction用于定义方法的返回值,与void一样。但是IBAction与IBOutlet一样没有特殊的意义,只是用来告诉interface builder,IBAction定义的方法可以作为连接到一个IBOutlet关键字申明的target的action。
相关问题
@interface中定义的变量与@property定义的变量的区别?
- 在@interface中定义的变量只有在当前类中访问;而@property申明的变量可以在类的外部访问。
- 用@property中申明的变量可以使用"self.variableName"方式读写变量,而在@interface中定义的变量就不行。
category与protocal的区别?
- category相较于protocal而言,代码较为松散。一个类可以有多个category,容易出现方法的重名。当方法出现重名时,category的优先级高于类本身的。即,如果类有一个functionA()方法,category也有一个同名的方法,我们在使用functionA()时会调用category的functionA()。
- interface中并没有对方法的实现,而是继承interface的子类需要对interface中方法进行实现;而category则会实现定义扩展的方法。