本文假定读者具备c语言或者其他语言的背景,快速上手Objective-C,或做参考之用。
基础
C语言的扩展
Objective-C很大程度上兼容C语言,是C语言的扩展,所有以@
开头的语言,都是扩展语法。在Objective-C中写C/C++是很容易的事情,只需要使用.cpp文件即可,Objective-C完全兼容。虽然OC是兼容C++的,但如果使用后缀m的文件编译,会找不到标准stl库,需要修改m后缀为mm。
Hello World
#import <Foundatioin/Foundation.h>
int main(int argc, const char * argv[])
{
NSLog(@"Hello, World!");
return (0);
}
Objective-C头文件以.h结尾,源文件以.m结尾。
注释
Objective-C 注释与 C++ 相同,符号: //
或者 /* */
导入
与C语言中的 #include <>
相对应的导入 #import <>
基本类型
Objective-C 中的基本类型同C,包括 bool
, char
, int
, long
, float
, double
, int
等。另外,在Foundation
库中,这些类型还定义了别名,NSInteger
对应有符号整数,NSUInteger
对应无符号整数,CGFloat
对应浮点数,BOOL
对应布尔值。
数字对应的对象还有 NSNumber
,可以跟基本的数字类型相互转化,详细信息可参阅 NSNumber Class Reference。
字符串
常量字符串可以用@""
结构表示,另外变量使用NSString
表示不可变字符串 ,NSMutableString
表示可变字符串。具体NSString
和普通C字符串的转换,可参阅NSString Class Reference
数组
之前提到的,在Objective-C中可以无障碍使用C语言的数据,不过OC还提供了数组类 NSArray
和NSMutableArray
,前者是不能修改的数组,后者支持增删操作,具体用法示例如下。
插入操作:
NSMutableArray * array = [NSMutableArray arrayWithCapacity:50];
[array addObject:[NSNumber numberWithUnsignedLongLong:123]];
[array addObject:[NSNumber numberWithUnsignedLongLong:456]];
遍历操作:
NSLog(@"Array Size: %u", (int)[userIdList count]);
// method one
for(int i=0;i<[array count];i++)
{
NSLog(@"%@",[array objectAtIndex:i]);
}
// method two
id ob;
NSEnumerator *enumerator = [array objectEnumerator];
while(ob=[enumerator nextObject])
{
NSLog(@"%@",ob);
}
// method three
for (NSNumber *num in array) {
if ([num isKindOfClass:[NSNumber class]]) {
NSLog(@"Elem: %llu", [num unsignedLongLongValue]);
}
}
可以看出,NSArray
可以插入任何对象,遍历可使用isKindOfClass
识别哪种数据类型。详细的操作可参照NSMutableArray Class Reference。
面向对象
interface
@interface Circle : NSObject
{
ShapeColor fillColor;
}
- (void) setFillColor : (ShapeColor) fillColor;
- (void) draw;
@end
- 程序开始
@interface
表示C的扩展语法,表示接口,继承自NSObject
ShapeColor fillColor;
声明了成员- (void) draw;
表示方法,前面的括号中表示方法的返回类型- (void) setFillColor : (ShapeColor) fillColor;
冒号后面的部分,表示有一个参数fillColor
,类型是ShapeColor
方法调用
Objective-C 调用对象方法的基本语法如下:
[object method];
[object methodWithInput:input];
同样可以调用类的方法:
id myObject = [NSString string];
其中id
表示myObject
类型,可以承载任何对象。
在很多语言中支持嵌套调用,如function1 ( function2() );
,Objective-C中可以同样可以写为:
[NSString stringWithFormat:[prefs format]];
多参数调用:
// 声明:-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
BOOL result = [myData writeToFile:@"/tmp/log.txt" atomically:NO];
implementation
之前的interface
只是声明了接口,具体的实现如下:
@implementation Circle
- (void) setFillColor: (ShapeColor) c
{
fillColor = c;
}
- (void) draw
{
NSLog(@"drawing");
}
@end
解释:
- 开始
@implementation Circle
表示为某个类提供代码。 - 接下来是方法定义,
fillColor = c
隐含self->fillColor
,表示当前对象的成员,调用方法时,circle setFillColor: kRedColor
,方法将circle
作为self
参数进行传递。
属性
@interface
属性定义:
// 头文件
@interface TestMessage : NSObject {
NSMutableArray * elems;
}
@property(nonatomic,retain) NSMutableArray* elems;
@end
// 实现文件
@implementation IMMessage
@synthesize elems;
@end
关键字@property
和@synthesize
含义如下:
// 头文件中:
@property int count;
// 等效为声明两个方法:
- (int)count;
- (void)setCount:(int)newCount;
// 实现文件中:
@synthesize count;
// 等效两个方法的实现
- (int)count
{
return count;
}
-(void)setCount:(int)newCount
{
count = newCount;
}
声明property的语法格式为:@property (参数1,参数2) 类型 名字;
参数的含义如下:
readwrite: 产生setter\getter方法
readonly: 只产生简单的getter,没有setter。
assign: 默认类型,setter方法直接赋值,而不进行retain操作
retain: setter方法对参数进行release旧值,再retain新值。
copy: setter方法进行Copy操作,与retain一样
nonatomic: 禁止多线程,变量保护,提高性能
实例化
对象的实例化:shape = [Circle new];
私有成员
对于私有变量,可以在 .m
文件中声明一个 name
私有变量:
@interface Circle (){
NSString* name;
}
对于私有方法,可以实现为:
@interface Circle (Private)
- (NSString*) GetName;
@end
@class
当两个类有循环依赖,如A类引用到B,B类又引用到A,import的时候没办法把两个类都放到自身前面,无法编译通过,这事可以A类中使用@class B
来声明有一个类B,具体实现在其他地方,来解决循环依赖问题。
高级特性
selector
Objective-C
中的方法调用就是消息传递,除了使用[]
来传递消息以外,还有一种在运行期间进行消息传递的方法,就是selector
方式,不同参数的消息传递如下:
// 无参数
- (void) fooNoInputs {
NSLog(@"Does nothing");
}
[self performSelector:@selector(fooNoInputs)];
// 一个参数
- (void) fooOneIput:(NSString*) first {
NSLog(@"Logs %@", first);
}
[self performSelector:@selector(fooOneInput:) withObject:@"first"];
// 多个参数
- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second {
NSLog(@"Logs %@ then %@", first, second);
}
[self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second"];
另外,在selector
中可以使用onThread
参数指定所执行方法的线程。
内存管理
在之前的OC版本中,需要对象操作alloc
,release
等手工进行分配释放,一旦管理不善,容易出现内存泄漏或者崩溃。在Xcode 4.2中,增加了自动引用计数Automatic Reference Counting, ARC
,不需要开发者考虑release
的问题,详情可参考理解 Objective-C 的 ARC。