基本的数据类型
1. int float double long char bool等
其中bool的值为YES,NO
nil相当于java中的null
2. id类型:类似Java 的Object 类,可以转换为任何数据类型,id类型已经是指针了,所以变量不需要加*
id foo=nil;
创建一个类
通常会编写.h和.m
.h文件用于变量与方法的声明.m是方法的实现。
1. 类定义:在@interface与@end之接。
2. 通常情况@符号后面紧跟关键字。
3. @interface Fraction : NSObject中:Fraction为子类,NSObject为父类
4. { }花括号中间进行变量的声明
5. -表示对象方法,+表示类方法
6. 实例化一个对象:
Fraction *fraction=[Fraction alloc]; //为fraction分配内存,alloc方法从父类继承
[fraction init]; //对fraction对象进行初始化,可以编写自己的init方法进行初始化
以上两个语句可以合并为:
Fraction *fraction=[[Fractionalloc]init];
但是嵌套不要太多,不好理解
7. 方法调用(oc中称为给对象发送一个消息):
对象方法调用,[fractionprint];
类方法调用,[Fractionversion];
8. import相当于c中的include,对已经导入的头文件不再导入,防止重复导入头文件。
9. Foundation/Foundation.h包含了大部分你会用到的基础类
10. 权限问题:一共有private(自己),protected(自己与子类),public(自己,子类,其他类),package四种,默认的变量权限为protected,方法只能为public
{
@private
int privateVar;
@public
double publicVar;
@protected
int protectedVar;
}
11. 方法定义:
-(void)setNumerator:(int)nandDenominator:(int)d;
其中方法名为
setNumerator: andDenominator:
注意第一个冒号后面有空格,这是一个完整的方法名,一般来说有多个参数的方法,有几个参数就有几个标示,所有的标示组成完整的方法名。
1. 类的实现:在@implementation与@end之间
2. self相当于Java中this,同样有super同java中super
继承,重写覆盖,重载
1. oc中只能单继承
2. 子类可以重写父类的方法,对其进行覆盖。
子类内部还能调用父类的该方法,使用super
[super method];
3. oc不支持重载,即使参数不一样也不能使用同名方法
点操作符(property)
1. 由于oc中默认变量时私有的,所以一般要通过设置器和访问器来访问变量。
访问器一般与变量名同名,设置器在变量名前加set变量名第一个字母改为大写。
Fraction *fraction=[[Fractionalloc]init];
[fraction setNumerator:1];//调用设置器
int num=[fraction numerator];//调用访问器
2. Objective-C 2.0新增了点操作符的设置器(setter)和获取器(getter)
以上代码等同于1中的代码。即编译器会自动帮我们实现这四个方法
-(void)setNumerator:(int)n;
-(void)setDenominator:(int)d;
-(int)numerator;
-(int)denominator;
3. 采用2中方式后
Fraction *fraction=[[Fractionalloc]init];
fraction. numerator =1;
int num= fraction. numerator;
当然用1中的代码效果是相同。
4. 关于@synthesize
在.m文件中可以加也可以不加,不加的话系统默认帮你做一个操作
@synthesizenumerator= numerator;
有时是会加下划线@synthesizenumerator= _numerator;
5. @property int numerator;可以通过增加修饰符(atomic,nonatomic,readonly,readwrite,assign,retain,copy)来改变访问器与设置器的实现方式。
比如@property (readonly)NSString*name;那么将只会产生访问器,没有设置器。
6.关键字的解释(建议看完内存管理后再看)
atomic,nonatomic:
atomic是默认属性,保证setter/getter的原子性,即线程同步。nonatomic不保证原子性
readonly,readwrite:
readwrite为默认属性,生成默认的setter/getter方法。readonly只生成getter方法。
assign:
默认属性,简单赋值,不改变引用计数(retainCount),用于基础数据类型 (NSInteger)和C数据类型(int,float, double, char,等),其中int这样的基本类型并不是对象,如果使用retain与copy会报错。
retain:
指定retain应该在后面的对象上调用,前一个值发送一条release消息。
如果声明@property(nonatomic,retian)obj;
那么代码self.obj = nil;等价于 [obj release]; obj = [nilretain];
copy:
建立一个索引计数为1的对象(内容与传进来的对象内容相同,地址不同),然后释放旧对象。他不会影响到传进来的对象。
如果声明@property(nonatomic,copy)obj;
那么代码self.obj = nil;等价于 [obj release]; obj = [newObj copy];
Categories类别(分类)
1. 为类扩充方法,而不需要采用继承的方式。
使用时,只需要在main.m
中导入Fraction+MathOps.h头文件,不需要改变Fraction类的代码,也不需要继承,即可为Fraction类扩充add,sub,div,mul四个数学操作相关的方便。同时使代码结构更加清晰。
protocol协议
1. oc中的协议非常类似Java中的接口,定义一个协议
以@protocol开头@end结尾
继承一个协议
在.m中实现协议中的方法
play,stop被required关键字修饰,所以必须去实现,pause被optional关键字修饰可以不去实现
2. 用协议修饰变量
定义一个变量:id<MyProtocolName> myNewVariable;
其中myNewVariable遵从我们制定的协议MyProtocolName
3. 用协议定义方法
- (void) doSomethingWithThisObject:(id<MyProtocolName>) aObject
4. 代理(委托)
Commandar类中定义了协议,定义了委托变量
Soldier遵循Order协议,所以实现了Order协议制定的方法
main中展示了委托代理与协议之间的关系。
即Commandar类制定了协议Order,Soldier类实现了协议内容,Commandar指定了Soldier作为代理,Commandar的这一行为称为委托。
多态,动态类型,动态绑定
1. id类型:通用指针类型,弱类型,编译时不进行类型检查
2. 多态:来自不同类型的对象可以定义共享相同名称的方法。(和java中的多态概念类似,用法有所区别)
动态类型:来自不同类可以定义共享相同名称的方法。
动态类型能使程序直到执行时才确定对象所属类型
动态类型:动态类型绑定能使程序直到执行时才确定要对对象调用的实际方法
3. 将一个变量定义为特定类的对象时,使用的是静态形态。
4. 当animal调用cry方法的时候系统会先检查animal中存储的对象所属的类,然后才会去动态的找到该类的cry方法并执行它。
5. 使用多态的特性优势很明显,很多情况下存在一些数据,只有运行时才知道类型,这时候使用动态类型,就非常合适简单。但不要滥用这一特性,系统同时提供了一些方法来检查动态类型,同样也可以使用@try @catch捕获异常。
SEL类型
1. SEL是选择器(selector)的一个类型。选择器就是指向方法的一个指针,SEL表示一个方法的名称。
@class
1. 当使用#import “xxx.h”时会把xxx类中的所有信息都导入,有时候不需要知道xxx类中存在哪些域,哪些方法,那么可以使用@class关键字。
使用方法把#import “xxx.h”替换为 @class xxx;这样编译器就知道文件中使用了xxx类。
全局变量
1. 实现全局变量方式一
直接通过类方法访问:[A instanceCount];即可,同样可以添加一个类方法对静态变量count进行修改,实现修改全局变量的功能。
2. 方式二:与c语言中方式一样使用extern关键字,即在主程序入口文件中对一个变量进行外部引用的声明,在其他文件中当需要使用该变量时,同样先声明这是一个外部变量,然后可以对其进行访问修改。
类扩展class extension
1. 类扩展的形式
在.m文件中,在@interfaceA ()与@end之间定义需要扩展的内容。
2. 你可以再类扩展中添加方法和变量,默认都是私有的。这一点区别于Categories类别,在类别中只能定义方法不能定义变量。
3. 在类扩展中可以改变一个已经定义的变量,这样可以使得这个变量对其他人事只读的,对自己是读写的
for in
1. 类似于java中的for(A a:aList)
oc中可以使用for in对一个集合进行遍历。
NSMutableArray*bunchOfThings = [[NSMutableArray alloc] init];
[bunchOfThingsaddObject:@"One"];
[bunchOfThingsaddObject:@"Two"];
for(NSString*s in bunchOfThings)
NSLog([NSStringstringWithFormat:@"s=%@", s]);
内存管理
oc使用“引用计数(retainCount)”方式来管理内存。当该对象创建时,该计数为1,说明有一个引用,如果不用时,就会减为0,这就表示不再使用了,那么就会销毁该空间。
1. alloc, allocWithZone,new(带初始化)
为对象分配内存,retainCount为“1”,并返回此实例。
2.retain
retainCount 加“1”
3.copy,mutableCopy
复制一个实例,retainCount数为“1”,返回此实例。所得到的对象是与其它上下文无关的,独立的对象(干净对象)。
4.release
retainCount 减“1”,减到“0”时调用此对象的dealloc方法
5.autorelease
把当前对象放入了当前的Autoreleasepool中,当该pool被释放时,该pool中的所有Object会被调用Release
我们可以把上面的接口按对retainCount的操作性质归为两类,
A类是加一操作:1,2,3
B类是减一操作:4,5(延时释放)
内存管理准则如下:
1,A与B类的调用次数保持一制
2,为了很好的保障准则一,以实例对象为单位,谁A了就谁B,没有第二者参与
内存管理ARC
1. 从XCode4.2开始就引入Automatic Reference Counting机制。我们创建的模板能看到@autoreleasepool{};
2. ARC使得你不需要再思考何时使用retain,release,autorelease这样的函数来管理内存,它提供了自动评估内存生存期的功能,并且在编译期间自动加入合适的管理内存的方法。编译器也会自动生成dealloc函数。
3. 基本的ARC使用规则
代码中不能使用 release, retain, autorelease,dealloc, retainCount
不重载dealloc(如果是释放对象内存以外的处理,是可以重载该函数的,但是不能调用[super dealloc])
不能使用NSAllocateObject, NSDeallocateObject
不能在C结构体中使用对象指针
id与void *间的如果cast时需要用特定的方法(__bridge关键字)
不能使用NSAutoReleasePool、而需要@autoreleasepool块
不能使用“new”开始的属性名称
ARC下的property
1. 用strong代替retain,copy
2. 用week代替assgin