1. ObjC中可以使用标准C++的文件,但是在ObjC中要使用的话请先把你的文件格式改成 .mm 的,不然编译肯定会报一大堆的错误。当然,你如果想在你的类中使用标准C++的类,要么引用头文件,要么就写类前导声明。不过这里要注意的是写法的问题。
例如,@Class MyClass; 大家都知道这个可以用来声明一个ObjC的类(interface),而想声明C++类,那么去掉@符号吧,和你在C++写法一样,Class MyClass; 简单吧。
2. 在ObjC中,类成员属性默认是私有的,想声明为公有,那么就这么写:
@interface MyClass
{
@public NSInteger iMember1;
@public NSInteger iMember2;
}
@end
不过要说明的是,就算你写成公有的了,我也没想到用什么办法不通过设置器和访问器直接修改或者读取这个成员,指针例外。
3. 引用头文件的方式,想必大家也知道#import的好处,不过提一点的是,如果你建立文件的时候,这两个文件只是关联的方式存在于你的工程,而存储位置并不是这个位置,那么X-Code说不定就会给你报出一个重复定义的错误的,那个时候先别想其他的,检查工程中的文件有没有少。当然,框架的添加除非必要,一般都是采取关联的方式添加到你的工程中的。
4. 开发中可能会频繁出现的,char *类型和NSString *类型的互相转换,这里介绍两个函数,相信足够大家使用了:
①char *转换为NSString *
+ (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)encoding
其中encoding是const char *的编码方式,只有知道了这个你才能完成转换
NSStringEncoding种类:
enum {
NSASCIIStringEncoding = 1,
NSNEXTSTEPStringEncoding = 2,
NSJapaneseEUCStringEncoding = 3,
NSUTF8StringEncoding = 4,
NSISOLatin1StringEncoding = 5,
NSSymbolStringEncoding = 6,
NSNonLossyASCIIStringEncoding = 7,
NSShiftJISStringEncoding = 8,
NSISOLatin2StringEncoding = 9,
NSUnicodeStringEncoding = 10,
NSWindowsCP1251StringEncoding = 11,
NSWindowsCP1252StringEncoding = 12,
NSWindowsCP1253StringEncoding = 13,
NSWindowsCP1254StringEncoding = 14,
NSWindowsCP1250StringEncoding = 15,
NSISO2022JPStringEncoding = 21,
NSMacOSRomanStringEncoding = 30,
NSUTF16BigEndianStringEncoding = 0x90000100,
NSUTF16LittleEndianStringEncoding = 0x94000100,
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100,
NSProprietaryStringEncoding= 65536
};
②NSString *转换为char *
- (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding
用法基本同上,相信有了这两个方法,加上你对于C的了解,所有的字符串问题应该不会再困扰你了。
5. 举例说明一个ObjC类的实现
// NSCustomClass.h
// 自定义类头文件
#import
@interface NSCustomClass : NSObject
{
NSString* stringValue; // 字符串属性
NSInteger intValue; // 整型属性
}
// 访问器(getter)声明(外部通过以下接口访问成员属性)
- (NSString*)stringValue;
- (NSInteger)intValue;
// 设置器(setter)声明(外部通过以下接口设置成员属性)
- (void)setStringValue: (NSString*)input;
- (void)setIntValue: (NSInteger)input;
@end
// NSCustomClass.m
// 自定义类实现文件
#import "NSCustomClass.h"
@implementation NSCustomClass
// Begin 访问器实现
- (NSString*)stringValue
{
return stringValue;
}
- (NSInteger)intValue
{
return intValue;
}
// End 访问器实现
// Begin 设置器实现
- (void)setStringValue: (NSString*)input
{
[stringValue autorelease]; // 防止入参与成员属性的地址相同(该释放过程会在函数执行结束后进行)
stringValue = [input retain]; // 为属性赋值(此处采取增加内存引用计数的方式)
}
- (void)setIntValue: (NSInteger)input
{
intValue = input; // 简单类型直接赋值
}
// End 设置器实现
// 实现自定义初始化方法(该方法不需要在头文件中声明)
- (id)init
{
if (self = [super init]) // 初始化基类
{
// 初始化自身成员属性
[self setStringValue:@"This is a string!"];
[self setIntValue:123];
}
return self; // 返回自身对象
}
// 实现自定义析构方法(姑且称之为析构,同样不需要在头文件中声明)
- (void)dealloc
{
[stringValue release];
stringValue = nil;
/* 上面两句等同于下面两句中的任何一句 /
ObjC中.操作符会调用该属性的设置器或者构造器 /
这是学C/CPP的人要特别明确的一点,非常重要 /
记住这一点可以避免很多内存泄露或者迷途指针的问题。
*/
// self.stringValue = nil;
// [self setStringValue: nil];
[super dealloc]; // 调用基类析构方法
}
@end
在此特别声明的是,如果你通过alloc方式或者copy关键字创建了一个对象,在函数结尾或者其拥有者释放的地方给它发送一个release或autorelease消息,如果是其他方式创建的,那就什么也别做。这一个“做”和一个“不做”同等重要!