一:Objective-C入门
1、Cocoa的组成
苹果公司将Cocoa、Carbon、QuickTime和OpenGL等技术作为框架集提供
Cocoa组成部分有:
Foundation框架(有很多有用的,面向数据的低级类和数据结构)
Application Kit(也称AppKit)框架(包含了所有的用户接口对象和高级类,例如NS……)
,还有一个支持框架的套件,包括Core Animation和Core Image。
2、NSLog相当于printf()
NSLog(@"hello Objective-C");
//注:@是Objective-C在标准C语言基础上添加的特征之一,双引号的字符串前面有一个@,这表示引用的字符串应该作为Cocoa的NSString元素处理
NSLog(@"are %d and %d different? %@",5,5,boolString(areTheyDifferent));
//注意%@:使用NSLog输出任何对象值时,都会使用这个格式说明
3、BOOL使用8位存储,YES定义为1,NO定义为0,大于1不为YES,跟标准C不同。
若不小心将一个长于1字节的整型值赋给BOOL,则只截取低八位
Obejective-C中1不等于1,绝对不要将BOOL值和YES比较
二:面向对象的Objective-C
4、使用间接从本地读取文件的例子
#import
int main(int argc,const char * argv[])
{
if(argc == 1){
NSLog(@"you need to provide a file name");
return (1);
}
FILE *wordFile = fopen(argv[1] , "r");
char word[100];
while (fgets(word,100,wordFile)){
//fget调用会保留分开每一行的换行符,我们不需要,把它替换为0,表示字符串的结束
word[strlen(word)-1] ='\0';
NSLog(@"%s is %d characters long",word,strlen(word));
}
//运行用 ./Word-Length-4 /tmp/words.txt
若给了文件路径,那么argc会大于1,然后我们可以查询argv数组得到文件路径。argv[1]保存着用户提供的文件名,argv[0]保存着程序名。
在XCode中编译此程序需要在XCode文件列表中展开Executables,双击程序名,在Arguments区域中添加启动参数
5、id
id是一种泛型,用于表示任何类的对象,id实际上是一个指针,指向其中的某个结构
6、[]
例[shape draw]
第一项是对象名,其余部分是要执行的操作
7、Objective-C的OOP范例
1)@interface部分(一般都作为.h单独书写,声明部分)
@interface Circle:NSObject //说明这是为Circle的新类定义的接口
{
ShapeColor fillColor;
ShapeRect bounds;
} //括号内的是Circle对象需要的各种数据成员
- (void) setFilColor:(ShapeColor) fillColor; //先行短线表明“这是新方法的声明”如果是“+”则表示是类方法,也称工厂方法
- (void) setBounds:(ShapeRect) bounds;
- (void) draw;
@end //Circle
2)@implementation部分(一般写为.m文件,实现部分)
@implementation Circle //@implementation是一个编译器指令,表明你将为某个类提供代码
- (void) setFillColor:(ShapeColor) c //在这里如果继续使用参数名fillColor,就会隐藏fillColor实例变量,并且有警告
//我们已经定义了一个名为fillColor的实例变量,可以在该方法中引用该变量,如果使用相同的另一个变量,那么前一个会屏蔽
{
fillColor = c;
}
- (void) setBounds:(ShapeRect) b
{
bounds = b;
}
- (void) draw
{
NSLog("^^^")
}
@end //Circle
可以在@implementation中定义那些在@interface中无相应声明的方法,可以把他们看做是石油方法,仅在类的实现中使用。
注:Objective-C不存在真正的私有方法,从而禁止其他代码调用它。这是Objective-C动态本质的副作用。
8、中缀符(infix natation)
方法的名称和及其参数都是合在一起的
例如
一个参数:
[citcle setFillColor : KRedColor];
两个参数:
[circle setStringValue : @”hello there” color : KBlueColor];
9、继承(X是一个Y,isa)
1)Objective-C不支持多继承,我们可以通过Objective-C的其他特性获取多继承的优点,例如分类和协议
2)继承中方法的定义
可以使用空正文和一个虚(dummy)值都是可以的
3)方法调度
当代码发送消息时,Objective-C的方法调度将在当前分类中搜索相应的方法,如果找不到,则在该对象的超类中进行查找
4)实例变量
10、复合(X有一个Y,has)
严格的讲,只有对象间的组合才叫做复合,诸如int、float、enum和struct等基本类型都认为是对象的一部分
11、init
- (id) init
{
if (self = [super init]) { //将[super init]得结果赋给self是Objective-C的标准惯例,为了防止超类的初始化过程中返回的对象不同于原先创建的对象
//若要超类要完成所需的一次性初始化,需要调用[super init],init方法返回的值描述了被初始化的对象
engine = [Engine new];
tires[0] = [Tire new];
tires[1] = [Tire new];
tires[2] = [Tire new];
tires[3] = [Tire new];
}
return (self);
} // init
12、存取方法(accessor method)
setter和getter
setter方法根据他所要更改的属性的名称来命名,并加上set
getter方法根据其返回的属性的名称来命名,不要加get
三:源文件组织
13、@class * 和import *.h
@class创建一个类前声明,告诉编译器:相信我,以后你会知道这个到底是什么,但是现在,你只需要知道这些
继承一个类的时候不能用@class,因为他们不是通过指针指向其他类,所以继承一个类时要用import *.h
四:Xcode的使用
14、更改自动注释中的公司名
终端中:
defaults write com.apple.apple.Xcode PBXCustomTemplateMacroDefinitions
‘{“ORGANIZATIONNAME” = “iPhone_xiaoyuan.com”;}’
没有任何输出结果
15键盘符号
1)Mac按键符号
|
2)Microsoft键盘和Mac键盘的对照
Alt->
徽标键->Option
16、Xcode技巧
1)同步显示
有时候两个窗口中显示的内容并不是同步的,只有分别单击了它们,才能同步更新内容
2)首行缩进
选自,右键->Re-indent selection
Alt [ 和 Alt ]可以把选中的代码左移和右移
3)代码自动完成
Tab 键可以按频率最高的填充完成词
Esc 可以弹出提示列表(E表示枚举,f代表函数,#代表@define,m表示方法,C表示类)
Ctl+. 在各选项中切换
Shift+Ctrl+. 反向循环
control+/ 在占位符之间切换
4)批量编辑
快照:File->Make Snapshot
查看快照:File->Snapshot
一次改变文件中的相同字符:选定,Edit->Edit all in Scope,更改的时候都会变
重构:选定,Edit->Refactor,弹出对话框,输入要改成的字符(选中Snapshot后可以看见改变)
5)键盘代替鼠标
■ control-F: Move forward, to the right (same as the right arrow).
■ control-B: Move backwards, to the left (same as the left arrow).
■ control-P: Move to the previous line (same as the up arrow).
■ control-N: Move to the next line (same as the down arrow).
■ control-A: Move to the beginning of a line (same as the as command- left arrow).
■ control-E: Move to the end of a line (same as the as command- right arrow).
■ control-T: Transpose (swap) the characters on either side of the cursor.
■ control-D: Delete the character to the right of the cursor.
■ control-K: Kill (delete) the rest of the line. This is handy if you want to redo the end of a line of code.
■ control-L: Center the insertion point in the window. This is great if you’ve lost your text cursor or want to quickly scroll the window so the insertion point is front and center.
6)任意搜索
在菜单栏上面搜索
7)快速打开
#import后的文件选中,File->Open Quickly,Xcode就会打开文件。若不选择,则会打开Open Quickly对话框
8)打开文档
Option+双击
9)调试时看数据
鼠标放在上面一会就可以看到
五:Foundation Kit
17、一些有用的数据结构 (结构体能减少过程中的开销)
1)NSRange //用来表示相关事物的范围
typedef struct _NSRange {
unsigned int location;
unsigned int length;
} NSRange;
例如“Objective-C is a cool language”中,“cool”可以用location为17,length为4的范围来表示
有3种方式可以创建新的NSRange
第一种:直接给字段赋值
NSRange range;
range.location = 17;
range.length = 4;
第二种:应用C语言的聚合结构赋值机制
NSRange range = { 17, 4 };
第三种:使用Cocoa提供的快捷函数NSMakeRange():
NSRange range = NSMakeRange(17,4);
//使用NSMakeRange()的好处是可以在任何使用函数的地方使用他
//例如 [anObject flarbulateWithRange: NSMakeRange (13, 15)];
2)几何数据类型
typedef struct _NSPoint {
float x;
float y;
} NSPoint;
typedef struct _NSSize {
float width;
float height;
} NSSize;
typedef struct _NSRect {
NSPoint origin;
NSSize size;
} NSRect;
//Cocoa也为我们提供了这些类型的快捷函数:NSMakePoint()、NSMakeSize()和NSMakeRect()
18、字符串(NSString和NSMutableString)
A:不可变的字符串(NSString)
1) 创建不可变的字符串
函数:+ (id) stringWithFormat: (NSString *) format, ...;
使用方法:
NSString *height;
height = [NSString stringWithFormat:@"Your height is %d feet, %dinches", 5, 11];
2)NSString类中的方法
①大小
函数:- (unsigned int) length;
使用方法:
if ([height length] > 35) {
NSLog (@"wow, you're really tall!");
}
②比较
函数1:- (BOOL) isEqualToString: (NSString *) aString;
使用方法:
NSString *thing1 = @"hello 5";
NSString *thing2;
thing2 = [NSString stringWithFormat: @"hello %d", 5];
if ([thing1 isEqualToString: thing2]) {
NSLog (@"They are the same!");
} //应用这个函数,不能用“==”,“==”只能比较字符串的指针值
函数2:- (NSComparisonResult) compare: (NSString *) string;
其中
typedef enum _NSComparisonResult {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
} NSComparisonResult;
使用方法:
[@"aardvark" compare: @"zygote"] return NSOrderedAscending:.
[@"zoinks" compare: @"jinkies"] return NSOrderedDescending. And,
[@"fnord" compare: @"fnord"] return NSOrderedSame.
不区分大小写的比较
函数: - (NSComparisonResult) compare: (NSString *) string
options: (unsigned) mask;
options参数是一个位掩码,可以用位或运算符(|)来添加这些选项标记
一些常用的标记有
■ NSCaseInsensitiveSearch: 不区分大小写
■ NSLiteralSearch: 进行完全比较,区分大小写
■ NSNumericSearch:比较字符串的字符个数,而不是字符值,若没项,“100”会排在“99”前面(一定要加)
使用方法:
if ([thing1 compare: thing2
options: NSCaseInsensitiveSearch|NSNumericSearch]== NSOrderedSame) {
NSLog (@"They match!");
}
③包含字符串判断
函数:
- (BOOL) hasPrefix: (NSString *) aString; //判断开头
- (BOOL) hasSuffix: (NSString *) aString; //判断结尾
- (NSRange) rangeOfString: (NSString *) aString; //看字符串中是否包含其他字符串
使用方法:
NSString *filename = @"draft- chapter.pages";
if ([fileName hasPrefix: @"draft") {
// this is a draft
}
if ([fileName hasSuffix: @".mov") {
// this is a movie
}
NSRange range;
range = [fileName rangeOfString: @"chapter"];
//返回range.start为6,range.length为7,若传递的参数在接受字符串中没有找到,那么range.start则等于NSNotFound
B)可变字符串(NSMutableString)
1)创建可变的字符串
方式1:
函数:+ (id) stringWithCapacity: (unsigned) capacity; //这个容量只是给NSMutableString的一个建议
使用方法:
NSMutableString *string;
string = [NSMutableString stringWithCapacity: 42];
方法2:
继承NSString中的方法
NSMutableString *string;
string = [NSMutableString stringWithFormat: @"jo%dy", 2];
2)NSMutableString中的方法
函数:
- (void) appendString: (NSString *) aString;
- (void) appendFormat: (NSString *) format, ...;
- (void) deleteCharactersInRange: (NSRange) range; //配合rangeOfString:一起连用
使用方法:
NSMutableString *string;
string = [NSMutableString stringWithCapacity: 50];
[string appendString: @"Hello there"];
[string appendFormat: @"human %d!",39];
NSMutableString *friends;
friends = [NSMutableString stringWithCapacity: 50];
[friends appendString: @"James BethLynn Jack Evan"];
NSRange jackRange;
jackRange = [friends rangeOfString: @"Jack"];
jackRange.length++; // eat the space that follows
[friends deleteCharactersInRange: jackRange];
19、NSArray和NSMutableArray
A) NSArray(不可改变的数组,是一个Cocoa类,用来存储对象的有序列表)
NSArray的两个限制
首先:它只能存储Objective-C的对象,而不能存储C语言中的基本数据类型,如:int, float, enum, struct,或者是NSArray中的随机指针
然后:不能存储nil
1)创建方法
通过类的方法arrayWithObjects:创建一个新的NSArray
使用方法:
NSArray *array;
array = [NSArray arrayWithObjects:@"one", @"two", @"three",nil];
//array是以nil结尾的,这是nil不能存储的原因
2)常用方法
- (unsigned) count; //获取数组包含的对象个数
- (id) objecAtIndex : (unsigned int) index ; //获取特定索引处的对象
- componentsSeparatedByString://切分NSArray
- componentsJoinedByString://合并NSString
使用方法:
int i;
for (i = 0; i < [array count]; i++) {
NSLog (@"index %d has %@.",i, [array objectAtIndex: i]);
}
NSString *string = @"oop:ack:bork:greeble:ponies";
NSArray *chunks = [string componentsSeparatedByString: @":"];
string = [chunks componentsJoinedByString: @" :- ) "];
B)NSMutableArray(可变数组)
1)创建方法,通过类方法arrayWithCapacity创建
+ (id) arrayWithCapacity: (unsigned) numItems;
使用方法:
NSMutableArray *array;
array = [NSMutableArray arrayWithCapacity: 17];
2)常用方法
- (void) addObject: (id) anObject;
- (void) removeObjectAtIndex: (unsigned) index;
使用方法:
for (i = 0; i < 4; i++) {
Tire *tire = [Tire new];
[array addObject: tire];
}
[array removeObjectAtIndex: 1]; //删除第二个
C)遍历数组的三种方式:通过索引、使用NAEnumerator和快速枚举
1)索引遍历 //只有在真的需要索引访问数组时才应使用-objectAtIndex,例如跳跃数组或者同时遍历多个数组时
int i;
for (i = 0; i < [array count]; i++) {
NSLog (@"index %d has %@.",i, [array objectAtIndex: i]);
}
2)使用NSEnumerator //Leopard中被快速枚举替代
创建方法:通过函数 - (NSEnumerator *) objectEnumerator;
使用方法:
NSEnumerator *enumerator;
enumerator = [array objectEnumerator]; //如果想从后往前浏览集合,还有一个方法reverseEnumerator可以使用
创建后通过while循环,条件是nextObject( 方法原型 - (id) nextObject );
循环遍历的程序为:
NSEnumerator *enumerator;
enumerator = [array objectEnumerator];
id thingie;
while(thingie = [enumerator nextObject ]) {
NSLog(@“i found %@” , thingie);
}
//注:对可变数组进行枚举操作时,不能通过添加和删除对象这类方式来改变数组容器,如果这样做了,枚举器会觉得困惑,为你将会得到未定义结果
3)快速枚举
在Leopard中才开始的,Tiger中不能用
for (NSString *string in array ) {
NSLog(@“i found %@” , string);
}