改定履历:
2012-05-10-------------新建文本文档
正文:
本文原文地址
Objective-C 类
Objective-C 类的 interface
1. 声明实例变量和公有方法:MyString.h
#import <Cocoa/Cocoa.h>
@interface MyString : NSObject {
// Declare instance variables
NSString* value;
}
// Declare methods
- (NSString*) value;
- (void) setValue: (NSString*)input;
+ (NSString*) append:(NSString *)fromString target:(NSString *)toString;
@end
2. MyString类继承了预先定义的顶级objective-c类NSObject(根类)
※ NSObject类是objective-c基础框架的根类
※ 最佳实践;应用对象都应该是NSObject的子孙.
@interface MyString : NSObject {
3. 符号"+"的意思是,该方法是objective-c类方法
- (NSString*) value;
4. 符号"-"的意思是,该方法是objecitve-c实例方法.
- (NSString*) value;
5. 定义一个NSString指针类型的实例变量:
NSString* value;
※ "*"表示这是个指针类型.
※ 所有的objective-c对象变量都是指针类型.
※ 所有的实例变量缺省都是私有的,需要使用setter方法和getter方法访问实例变量.(译者注:缺省应该是保护的,作者的意思应该是在访问实例变量时不能直接引用).
※ 所有的实例变量初始化时都被置为nil.
6. 声明getter方法
- (NSString*) value;
※ 相比其它语言,这里的getter方法没有类似于"getValue"的前缀"get".
7. 声明setter方法:
- (void) setValue: (NSString*)input;
※ 以参数"input"来设置"value"的值.
8. 声明携带多个参数的访求:
+ (NSString*) append:(NSString *)fromString myTarget:(NSString *)toString;
※ objective-c处理多个参数与其它语言不同:
如同其它语言类似,上面的方法实际上是创建了一个名字为"append:myTarget:",携带参数"formString"和"toString"的方法.
obj.appendMyTarget(fromString, toString)
+ (NSString*) add:(NSString *)fromString value2:(NSString *)toString;
Objective-C 类实现(Implementation)
下面示例包含实现代码和私有方法:
MyString.m
#import "MyString.h"
@implementation MyString
- (NSString*) value {
return value;
}
- (void) setValue: (NSString*)input
{
[value autorelease];
value = [input retain];
}
@end
Objective-C 方法(Methods)
1. 给objective-c对象发送消息:
● 在objective-c中发送消息和在JAVA中调用一个方法等价
// Equivalent to myObject.myMethod(); in Java
[myObject myMethod];
// Equivalent to myObject.myMethod2(v1); in Java
[myObject myMethod2:v1];
// Equivalent to String result = myObject.method3(); in Java
NSString* result = [myObject myMethod3];
● myMethod3返回了NSString类型指针
● 接收消息的对象被称为接收者.
2.给objective-c类发消息
// Similar to NSString result = NSString.string(); in Java
NSString* result = [NSString string];
● 发送消息给NSString的类方法string.
3. 发送携带多个参数的消息:
// Similar to obj.add(v1, v2); in Java
[obj add:v1 value2:v2];
● "v1"和"v2"是objective-c方法"add:value2"的两个参数.
Method Declaration
// Similar to add(String fromString, String toString) in Java
+ (NSString*) add:(NSString *)fromString value2:(NSString *)toString;
● 方法参数区分顺序:
// Invalid
[obj value2:v1 add:v2];
● 如果声明了参数的话,参数不能像PHP或Ruby那样可选或带有缺省值.
// Invalid
[obj value2:];
4. 携带变量参数的方法:
[obj myMethod:v1, v2, v3, v4];
5. 在另一个消息内发送消息:
[obj myMethod1:[obj2 m1]];
● myMethod1携带的参数来自于:
[obj2 m1]
另一种形式:
[[obj getObj2] myMethod]
6. 发送消息给自身:
[self method];
● 实例方法内部,"self"意思是实例本身.
● 类方法内部,"self"意思是类本身(self refers to the class object)
7. 使用self创建新实例:
+ (id)createNewInstance
{
id newInstance = [[self alloc] init];
return [newInstance autorelease];
}
● 子类可以继承该方法 ,但仍需设法用下面的方式创建类实例:
[self alloc]
8. 给父类发消息:
[super method];
属性(Properties)
1. Getter/Setter方法声明:
@interface MyString : NSObject
{
@private
int value;
}
- (int)value;
- (void)setValue:(int)v;
@end
2. objective-c提供了一种自动产生setter方法和getter方法的声明和实现的机制.
● 使用"@property"声明getter/setter方法
MyString.h
#import <Cocoa/Cocoa.h>
@interface MyString : NSObject {
@private
NSString* value;
}
@property (retain) NSString* value;
@end
● 注意,getter方法和setter方法以下面几种方式之一实现:
○ 使用"@synthesize"自动产生getter和setter方法的实现.
MyString.m
@implementation MyString @synthesize value; @end
○ 使用携带等号的"@synthesize"@synthesize value = _value;
○ 等价于:@interface MyString : NSObject { @private int _value; }
@synthesize value;
○ 不使用@synthesize手动实现getter和setter方法:#import "MyString.h" @implementation MyString - (int)value { return value; } - (void)setValue:(int)v { value = v; } @end
○ 重载由"@synthesize"创建自动产生的方法:@implementation MyString @synthesize myTextArray; - (void)setMyTextArray:(NSMutableArray *)newArray { if (myArray != newArray) { [myArray release]; myArray = [newArray mutableCopy]; } } @end
● 使用符号"."来访问getter/setter方法:
obj1.value = @"Test value";
result = obj1.value;
调用getter方法,而不是直接访问实例变量:
self.value;
3. 使用不同的"getter/setter"方法名:
@interface MyString : NSObject
{
@private
int internal_value;
}
@property int value;
@end
@implementation MyString
- (int)value {
return internal_value;
}
...
@end
或
@synthesize value = internal_value;
(retain)会指示编译器在setter方法里自动的调用retain来增加引用计数
@property (retain) NSString* value;
@property其它选项:
1. 在setter方法里做一份输入参数"input"的拷贝,并赋值给v1:
@property (copy) NSString *v1;
2. 设置objective-c属性只读(只有getter方法而没有setter方法)
@property (readonly) NSString *v1;
3. 在分配(赋值)之前先对输入参数(input)retain
// Release the old value [value release];
// Retain the new value value = [input retain];
@property (retain) NSString *v1;
4. getter方法和setter方法不需要支持原子操作:
@property (nonatomic) NSString *v1;
● 原子操作(atomic)为多线程环境下访问属性提供支持,这个setter/getter方法操作总是原子的,并且会返回一个应得的值而非一个过渡值.
5. 在objective-c property中使用多个attribute
@property (retain, nonatomic) NSString *v1;
6. 拷贝数组对象需附加一些代码:
@property (nonatomic, copy) NSMutableArray *myTextArray;
● "copy"返回了collection(数组array)的不可变长版本.
如果要返回一个可变长数组:
@interface MyString : NSObject {
NSMutableArray *myTextArray;
}
@property (nonatomic, copy) NSMutableArray *myTextArray;
@end
getter方法和setter方法的"."符号:
1. objective-c为访问实例变量,对getter和setter方法提供了特别的语法访问器:obj1.value = @"Test value";
result = obj1.value;
● 这个语法仅用于getter和setter方法上.
● 下面是用于properties的典型示例:
obj1.amount += 10;
2. 类通过访问器来设置类实例:
self.value = @"Test value";
Objective-C type: id
1. objective-c预定义了一个ID类型,基本上所有objective-c对象都是ID类型:
id result = [NSString string];
● 任何对象都可以被指定为id类型.
● id类型意味着结果可以被引用,可以被指派为任意其它类型
id obj1 = [obj2 aMethod];
[obj1 someMethod];
●
因此,编译器不会去验证一个对象是否实现了一个特定的方法.
// Will not throw a compilationr error
[result someNonExistingMethod];
2. 如果返回值或参数没有明确声明类型,可假定其它为id类型.
- findMyObject:someParam;
- (id)findMyObject:(id)someParam;
objective-c的NSObject和id的不同
1. 声明一个object对象类型会把对象接口类的详细信息提供给编译器
2. 对id类型来说,只有在运行时(runtime)才能确定接口类(interface),和产生缺失的方法错误.
NSObject* obj = ...
NSObject对象是静态对象,调用不存在的方法会产生编译错误:
// Will throw a compilation error
NSObject obj1 = ...
[obj1 someMethodNotBelongToNSObject];
创建,初始化和释放(free)objective-c对象
创建和释放(free)objective-c对象
1. 为objective-c对象分配内存
[NSString alloc]
2. 为objective-c对象分配内存并初始化
NSString* obj1 = [[NSString alloc] init];
3. 释放(release)对象,包括一旦不会使用的内存
● release失败会导致内存泄露
[obj1 release];
● "init"方法返回的对象可能会和"alloc"返回的对象有所不同,所以应在同一行调用"alloc"和"init".
NSString* obj1 = [[NSString alloc] init];
初始化objective-c对象
初始化objective-c对象的实现代码:
- (id) init
{
if ( self = [super init] )
{
[self setValue:@"Set Default Value"];
}
return self;
}
● 调用父类初始化器初始化"self".
● 使用"if",以确保返回有效的对象.
self = [super init]
● "init"返回id类型
● 指派自身为"init"的返回值,因为该初始化器可能会返回不同于原始消息接收者的对象.
- (id) init
{
// Do not use the setter method self.someInstanceVariable = ...
someInstanceVariable = [[NSString alloc] init];
...
}
● "alloc"方法会增加引用计数
● 如果"init"方法使用了"setter"方法来设置实例变量,引用计数会再加1.
Objective-c自定义初始化器
1. 自定义init方法应以"init"前缀开始:
- (id) initWithCount:(int)count
NSString* obj1 = [[NSString alloc] initWithCount:30];
2. 在初始化方法里调用另一个初始化方法
- (id)initWithValue:(NSValue *)data {
// init method may return a new object
// assign the new object back to the self
self = [super initWithValue:data];
if (self) {
value = [data retain];
}
return self;
3. 增加error处理代码:
- (id)initWithValue:(NSValue *)data {
// release itself if data is nil
if (value == nil) {
[self release];
return nil;
}
self = [super initWithValue:data];
if (self) {
value = [data retain];
}
return self;
(便捷构造器)Convenience Constructors
1. 在Cocoa框架中,某些类方法绑定了"alloc"和"init"方法.被称之为便捷构造器(convenience constructors)
NSSTring* s = [NSString sting];
// no need to call [s release];
● 便捷构造器的调用者并不拥有该对象,因为无须释放(release)它.
● 便捷构造器通常调用"autorelease",在整个调用链结束的时候释放对象.
2. 便捷构造器的实现例子:
+ (id) createNewInstance:(NSString*) value
{
id newInstance = [[self alloc] init];
[newInstance setValue:value];
return [newInstance autorelease];
}
释放(free)objective-c对象(回收,de-allocate)
1. 回收(de-allocate)objective-c对象
- (void) dealloc
{
[value release];
[super dealloc];
}
● 如果需要,可release任意实例变量
● 调用父类的"dealloc"
● 如果垃圾回收机制有效的话,"dealloc"并不作用于对象(仅用于r Mac OS X).
● "dealloc会在运行时释放(free)对象时调用.
● 当垃圾回收机制有效时,实现"finalize"方法(When garbage collection is enabled, implement the finalize method)