(1)#import <Foundation/Foundation.h>中的Foundation.h是框架主头文件,相当于已经拷贝了Foundation框架下的所有头文件,需要导入这个头文件后,才能正常使用NSLog。
(2)框架存放在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library
(3)#import是#include的升级版,可以防止重复导入。
(4)NSLog已经包含自动换行。
(5)OC中得NSString长度计算的字数而不是字符数,如@“123哈哈”,长度是5。在C语言中length值是9,因为一个中文字符占3个字符长度。
(6)对象方法前面是-,类方法前面是+。类方法不可以访问成员变量(实例变量),如果方法不需要访问实例变量就用类方法,效率高。类方法只能用类调用,对象方法只能用对象调用。类方法不可以调用对方方法,对象方法可以调用类方法。类方法可以调用类方法。类方法和对象方法可以同名。
(7)当对象只需要调用一次的时候可用匿名对象。匿名对象可以作为实参传递。
(8)成员变量以下划线开头的好处之一:下方输入下划线就得到提示。
(9)self在类方法中就代表类,在对象方法中就代表对象。
(10)如果在子类中存在与父类同名的方法,称之为重写该方法。但是子类不能存在与父类相同的成员变量。
(11)super一般是明确告诉程序调用父类的东西。使用场景:一般是需要在子类中重写(添加增强)父类方法,但是原有的所有父类代码都能用,此时可用[super 方法名];把父类的那些代码都弄过来,然后再加上其他新增的代码,成为子类重写的方法。
(12)description方法用来输出对象的所有成员变量,当然自己也可以定制。
(13)没有继承就没有多态。多态就是用父类的指针指向子类的对象。如果子类重写了父类的方法后,就涉及到动态绑定为题,如果子类有重写,那么尽管用父类指针指向子类对象,程序在运行时会判断对象的真实类型(也就是用父类声明的那个对象指针),所以会调用子类的方法。除非子类没有重写该方法,只能调用父类的方法。
(14)接13,利用多态声明后,如果父类没有该方法子类有,会报错。这不是OC语言不支持,而是Xcode不支持。如果我们要继续使用,则需要强制转换,把父类声明的这个对象转换成子类声明的对象,然后再调用方法。
(15)点语法是OC为了迎合JAVA类程序员创造出来的。
(16)在子类中可以访问父类的@protected和@public成员变量,但不能访问@private成员变量。
(17)类的本质是一个类。在创建对象时,其实程序先把代码加载到代码区,然后再堆中创建了类对象,类对象的SEL指向了代码区中的方法,然后再利用类对象创建一个对象,这个对象的isa指向类对象,并在栈中存放了这个对象指针,指向这个对象。
(18)Class xxx=[类名 class];这个方法是获取类的类对象,xxx就是类对象。
(19)Person *p1=[Person new];这里p1以及self都是对象指针,它们指向的地址就是isa的地址。
(20)通过@property和@synthesize可以自动生成getter和setter方法,但是如果想控制输入数据的合理性,即setter赋值的合理性,可以重写setter方法。而且当自己同时手动设置setter和getter方法时,就不会为你自动生成成员变量。但一般我们都不会手动修改getter方法,所以一般不会同时重写这两个方法。
(21)用通用指针id接受一个对象后,要调用该对象的方法时不需要将id类型强制转换。
(22)重写init方法时,需要调用self=[super init];是固定写法。而且应该再后面增加一个判断if(self!=nil){},即只有父类初始化正常不反悔nil,才继续执行。死记硬背吧。优化写法就是if(self=[super init]){}。一般重写init,就似乎为了给某些属性固定值。
(23)类也不能互相在.h文件中#import导入。但可以利用@Class Person;代替(该语句仅仅是告诉编译器Person是一个类,这样就不会报错),且后者效率更高,在开发大型项目时会用到。有时候一般是在.h文件中用@Class ***,在.m文件中#import “***.h”,因为如果不导入的话,在.m中无法使用那个类的方法。
(24)所谓的内存管理:基本数据类型都是存放在栈中,作用域结束就自动失效。对象指针也是存放在栈中的,但对象指针指向的对象是存在堆中的,如果在作用域结束之前没有回收内存,那么对象指针被失效后,在堆中就会存在一个没有被回收的对象继续占用内存。
(25)当一个对象被回收时会调用类的dealloc方法,我们可以在重写这个dealloc方法。在重写时约定俗成在最后加[super dealloc];语句。
(26)当指针指向的对象引用计数为0时就会被销毁,那么此时这个指针就是一个野指针,因为它指向一个不存在的内存空间。
(27)一般如果有新的指针指向一个对象时们应该用retain为对象引用计数加1,否则直接指向的话,会有2个指针指向这个对象,但是其引用计数只有1,release一次就会出错。
(28)如果严谨一些的代码在对象指针release后,会把相应地对象指针设置为nil空值。
(29)用@property时候()里面:如果是OC对象类型则用retain/copy,基本数据类型就用assign。就是用到内存管理规则。
(30)系统自带的方法:如果不包含alloc、copy等,那么它们返回的对象都已经被autorelease过了。我们可以在创建对象的时候快速创建一个autorelease对象,这样别人在调用我们的对象时就不用考虑release的问题,此时创建最好用self而不用类名。
(31)ARC规则:只要没有强指针指向这个对象,就销毁这个对象。默认情况下所有指针都是强指针,而如果没有强指针指向时,尽管有弱指针,ARC也会自动删除弱指针。
(32)OC对象类型适用于强指针,相当于retain。基本数据类型适用于弱指针,相当于assign,所以在@property的()中用到:用strong或者assign。
(33)如果有以前项目的代码需要转换成ARC的,用如下方法。如果导入的第三方库有非ARC代码,则可以设置成保留非ARC。
(34)如果要循环引用的话,一个变量设置为strong,另一个设置为weak,否则出错。在非ARC时一个设置为retain一个设置为assign。
(35)苹果官方建议多用block封装代码,标记^,定义类似于定义变量,调用和函数调用一样。可以有参数和返回值等。一般情况下不可以在block内部修改局部变量,但是如果给局部变量添加__block关键字,它就可以在block中被修改。
01.
#
import
<Foundation/Foundation.h>
02.
03.
int
main(
int
argc,
const
char
* argv[]) {
04.
@autoreleasepool
{
05.
int
(^block1)(
int
,
int
)=^(
int
a,
int
b){
06.
return
a+b;
07.
};
08.
NSLog(@
"%i"
,block1(
5
,
6
));
09.
}
10.
return
0
;
11.
}
(36)类有继承有基类,协议同样,有基协议,也就是协议要遵守协议。
(37)可以在定义变量时候要求这个变量遵守某个协议,格式:类名 <协议名> *变量名;但是当类名是id时候,后面变量名的前面不需要*。同理,在@property声明属性的时候也能要求属性遵守某个协议,格式:@property (nonatomic,strong) 类名<协议名> *变量名称;同样当时id时后面的*去掉