1 . #import:Objective-C本质上就是C语言。和C语言一样,Objective-C使用头文件来包含元素声明,这些元素包括结构体、符号常量、函数原型等。#import可保证头文件只 被包含一次,而不论此命令实际上在那个文件中出现了多少次。
在C语言中,程序员通常使用#ifdef命令来避免一个文件包含另一个文件,而后者又包含第一个文件的情况。在OC中,使用#import来实现这个功能。
2 . NSLog():这个函数的作用和C语言的printf()很相似。NSLog()接受一个字符串作为第一个参数,该字符串可包含格式说明符(如%d)。此函数还可以接受匹配格式说明 符的其他参数。这里的“NS”是cocoa对其所有函数、常量和类型名称都添加了“NS”前缀。两个不同事物使用相同标识符时会导致名称冲突,而前缀可以预防这个大问题。
3 . 间接:基本变量就是间接的一种实际应用。文件也是间接的一种示例。
4 . Objective-C不支持多继承。例如:@interface Circle:NSObject, PrintableObject 编译器将不能识别。
5 . 超类:是你所继承的类。
父类:是超类的另一种表达方式。
子类:是实施继承的类。
孩子类:是子类的另一种表达方式。
6 . 多态性:使用更具体种类的对象(Rectangle或Circle)代替一般类型(Shape),这种能力称为多态性。
7 . super关键字:Objective-C提供某种方式来重写方法,并且仍然调用超类的实现方式。当需要超类实现自身的功能,同时在前面或者后面执行某些额外的工作时,这种机制非常有用。为了调用继承方法的实现,需要使用super作为方法调用的目标。向super发送消息时,实际上是在请求Objective-C向该类的超类发送消息。
8 . 如果用.mm做文件扩展名,编译器就会认为你是用Objective-C++编写代码,这样你就可以同时使用C++语言和Objective-C来编程了。
9 . 我们在程序里使用的都是#import<Foundation/Foundation.h>,因为这些程序都只用到了Cocoa的这一部分功能,但是将它替换成#import<Cocoa/Cococa.h>也是可以的。这条语句既导入了Foundation框架的头文件,也导入了其他一些文件。
10 . 导入头文件有两种方法:使用引号或者尖括号。例如#import“Button.h”或#import<Foundation/Foundation.h>,带尖括号的语句是用来导入系统头文件的,而带引号的语句则是说明导入的是项目本地的头文件。如果你看到的头文件名是用尖括号括起来的,那么这个头文件对你的项目来说是只读的,因为它属于系统。如果头文件名是被引号括起来的,那么你就可以编辑它。
11 . @class:对于循环依赖关系很有用。即A类使用B类,B类也使用A类,如果用#import语句让这两个类相互引用,就会出现编译错误。但是如果在A .h中使用@class B,在B.h中使用@class A,这两个类就可以相互引用了。
12 . Xcode使用技巧:
快捷键:1.command+[ 和command+] 可以把选定的代码左移或者右移。
2.command+control+s或者File-》Make Snapshot打开快照窗口,如果你修改错了想要恢复到原来,你就可以打开快照进行恢复了。
13 . NSRange 是一个结构体,它的定义为
typedef struct _NSRange{
int location;
int length;
}NSRange;
同样的结构体还有NSPoint、NSSize、NSRect
14 . 如果你在声明方法时添加了加号,那么就是把这个方法定义为类方法。这个方法属于类对象(而不是类的实例对象)并且通常用于创建新的实例。例如
+(id)stringWithFormat:(NSString *)format,...;方法就是一个类方法。
如果用减号来声明一个方法,那么这就是实例方法。我们所创建的大部分的方法都是实例方法。这些方法将会在某个对象实例中运行,比如获取一个Circle的颜色。
如果某方法用来实现常规功能,比如创建一个实例对象或者访问一些全局类数据,那么最好使用前导加号(+)将他声明为类方法。
15 . 比较两个字符串可以用-(NSComparisonResult)compare:(NSString *)string; // 该方法返回一个 NSComparisonResult(就是一个enum型数据)来显示比较结果。
typedef enum _NSComparisonResult {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
} NSComparisonResult;
16 . 如果检查两个对象thing1和thing2是不是同一个对象,就使用运算符“==”。
如果检查等价性(即两个字符串是否代表同一事物),就使用方法isEqualToString:。
17 . compare:方法进行的是区分大小写的比较。
-(NSComparisonResult) compare:(NSString *) string options:(uisinged) mask;
方法的参数options是一个位掩码。你可以使用位或运算符(|)来添加选项标记。一些常用的选项如下: NSCaseInsensitiveSearch:不区分大小写字符
NSLiteralSearch:进行完全比较,区分大小写。
NSNumericSearch:比较字符串的个数,而不是字符值。
18.NSArray:只能存储Objective-C的对象,不能存储基本数据类型,如int、float、enum、struct,或者NSArray中的随机指针。也不能在NSArray中存储nil,因为在列表结尾添加nil代表列表结束。
19.使用枚举NSEnumerator来遍历数组
NSEnumerator *enumerator;
enumerator = [array objectEnumerator];
id thing;
while (thing = [enumerator nextObject]) {
NSLog("I found %@", thing);
}
20.NSArray和NSDictionary只能存储对象,而不能直接存储任何基本类型的数据,如int、float、struct。你可以用对象NSNumber来封装基本数值。
例如,将int型数据封装到一个对象中,然后就可以将这个对象放入NSArray和NSDictionary中。
NSNumber *number = [NSNumber numberWithInt:42];
[array addObject:number];
21.将一个结构体放入NSArray中。
NSRect *rect = NSMakeRect(1, 2, 30, 40);
NSValue *value = [NSValue valueWithBytes:&rect objCType:@encode(NSRect)];
[array addObject:value];
可以使用方法getValue:来提取数值:(调用getValue:时,要传递的是要存储这个数值的变量的地址)
value = [array objectAtIndex:0];
[value getValue:&rect];
还有一种便捷的方法:
value = [NSValue valueWithRect:rectt];
[array addObject:value];
22.代表主目录的速记符号:~ 用法如下:
NSString *home = [@"~" stringByExpandingTildeInPath];
// stringByExpandingTildeInPath方法将“~” 替换成当前用户的主目录
23.内存管理规则:
1.当你使用new、alloc、copy方法创建一个对象时,该对象的保留计数器值为1。当不再使用该对象时,你要负责向该对象发送一条release或autorelease消息。这样,该对象将在其使用寿命结束时被销毁。
2.当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理。如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它。
3.如果你保留了某个对象,你需要(最终)释放或自动释放该对象。必须保持retain方法和release方法的使用次数相等。
24 . 点表达式:如果点表达式出现在等号左边,该属性名称的setter方法将被调用。如果 出现在右边,则getter方法将被调用。例如:str.length = 10; int length = str.length;
25 . 如果想要特性的名称和支持特性的实例变量的名称不相同,只需要在.h文件中修改实例变量的名称,并在.m文件中写上@synthesize 特性名称 = 修改后的实例变量名称。
例如 在Car.h文件中
NSString *application // 定义一个实例变量
@property(nonatomic, copy) NSString *name; // 定义一个特性
如果你希望application是支持特性 name 的实例变量的名称,则在Car.m文件里
@synthesize name = application 即可。
这样,我们在访问实例变量的时候用这种方法:self.name = @"Car";
26 . 当设置一个特性为只读特性时,编译器将只为该属性生成一个getter方法,而不会生成setter方法。
27 . 为现有的类添加新方法,这些方法叫做类别(category)。类别的声明和类的声明方式一样。
28 . 类别的局限性:
1 . 类别不能添加新的实现变量,所以类别的声明中没有实例变量部分。
2 . 名称冲突,即类别中的方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。你的类别方法将完全取代初始方法,从而无法再使用初始方法。
29 . 不但可以将一个类的实现分散到多个不同的源文件中,还可以将其分散到多个不同的框架中。
30 . 复制分为深层复制和浅层复制:
浅层复制(Shallow copy):不复制引用对象,新复制的对象只指向现有的引用对象。NSArray类的copy方法是浅层复制。如果复制一个NSArray类的对象,该对象包含5个NSString类的对象,则你最终得到的是5个可供程序使用的字符串对象,而不是10个字符串对象。
深层复制:将复制所有的引用对象。如果NSArray的copy方法是深层复制,则在复制操作完成以后你将得到10个可用的字符串对象。