Objective-C自上世紀(jì)80年代發(fā)展到至今(2018年)已經(jīng)有30多年了。目前Objective-C的版本相比于其他一些經(jīng)典的主流編程語言(Java罢屈、Python等)還是有些碎的后豫。目前對(duì)Objective-C的進(jìn)化起帶頭作用的仍然是Apple Inc.公司驯镊,而LLVM-Clang編譯器也能支持不少現(xiàn)代化的Objective-C語法特性燥狰,詳細(xì)請(qǐng)見:自O(shè)bjective-C 2.0以來的新增語法特性圈驼。而GCC從4.2之后就基本中斷了對(duì)Objective-C的升級(jí)梳码,當(dāng)前這里主要是指gobjc編譯器隐圾,我們?cè)诔鼳pple以外的其他類Unix系統(tǒng)上主要使用的GNUStep還是在不斷升級(jí)中,尤其是配合Clang對(duì)Objective-C的新增語法支持所新增的一些方法接口掰茶。
筆者撰寫本文的目的是為了提醒Objective-C程序員暇藏,如果自己所寫的代碼想在其他類Unix上使用GCC+GNUStep進(jìn)行編譯運(yùn)行的話所需要注意的一些事項(xiàng)。盡管GCC4.2比較老了濒蒋,但是還是有不少開發(fā)環(huán)境盐碱、硬件平臺(tái)不得不使用GCC,因?yàn)長(zhǎng)LVM-Clang目前所能支持的處理器架構(gòu)仍然不多沪伙,基本都屬主流處理器架構(gòu)瓮顽。所以在其他一些小眾平臺(tái)上開發(fā),那我們倘若沒能力自己修改Clang代碼進(jìn)行適配的話围橡,那么只能使用GCC了暖混。
下面,我先給出GNUStep的官方API參考文檔翁授,GNUStep中的Base類庫(kù)與Apple自家的Cocoa Framework中的Foundation類庫(kù)大部分都能兼容拣播,就是有些類的方法可能會(huì)稍微有些差異晾咪,我們?cè)诰唧w使用過程中如果遇到編譯報(bào)錯(cuò),可以進(jìn)行參考:GNUstep Base贮配。下面就開始我們的話題谍倦。
1、GCC中的Objective-C不能進(jìn)行自動(dòng)synthesize牧嫉,因此如果我們要聲明一個(gè)property并且不想自己實(shí)現(xiàn)其getter與setter方法的話就需要自己寫@synthesize
剂跟。此外,我們還需要在類中聲明使用此property所對(duì)應(yīng)的成員變量酣藻。
2曹洽、GCC中的Objective-C,Category不能聲明成員變量辽剧,只能聲明方法與property送淆。再結(jié)合第一條,如果我們?cè)贑ategory中聲明了一個(gè)property怕轿,并且在類中沒有聲明此property對(duì)應(yīng)的成員變量偷崩,那么我們只能手動(dòng)實(shí)現(xiàn)其getter與setter方法。
3撞羽、其實(shí)在比較早的Objective-C中就已經(jīng)把“點(diǎn)語法”擴(kuò)展得比較深了阐斜。這意味著,即便在一個(gè)類中沒有聲明某個(gè)property诀紊,但是有符合getter/setter命名規(guī)則的方法在谒出,那么我們就可以使用點(diǎn)語法。不過這里需要注意的是邻奠,在GCC中比較有意思笤喳,如果一個(gè)類的類方法的返回類型是id
,那么用該類通過點(diǎn)語法去訪問該類方法的結(jié)果不能作為消息接受者碌宴!
4杀狡、GCC中的Objective-C,對(duì)于在類的實(shí)現(xiàn)中所定義的內(nèi)部方法贰镣,它們必須要放在調(diào)用這些方法的方法之前呜象,否則的話編譯器會(huì)有warning提示消息可能無法響應(yīng)”。或者可以用私有Category進(jìn)行在先聲明董朝。
如果大家不能一下子明白上述幾點(diǎn)的具體使用場(chǎng)景,那么我將使用一個(gè)簡(jiǎn)單的demo進(jìn)行解答:
#import <Foundation/Foundation.h>
@interface MyObject : NSObject
{
@private
/// 這里必須顯式聲明string實(shí)例屬性干跛,
/// 以提供手工synthesize的能力。
NSString *string;
}
@property (nonatomic, retain) NSString *string;
- (void)testMethod;
+ (id)classMethod;
@end
@protocol MyProt<NSObject>
- (void)testMethod;
@end
// GCC中Category也能實(shí)現(xiàn)協(xié)議
@interface MyObject()<MyProt>
/// GCC中祟绊,Category里也可以聲明一個(gè)property
@property (nonatomic, readonly, assign) int theValue;
/// 通過擴(kuò)展聲明innerMethod方法楼入,
/// 這樣可使得innerMethod能定義在MyObject中的任意空位
- (int)innerMethod;
@end
@implementation MyObject
@synthesize string;
- (void)dealloc
{
self.string = nil;
[super dealloc];
NSLog(@"MyObject is destroyed!");
}
+ (id)classMethod
{
return @"class method";
}
- (id)myself
{
NSLog(@"This is myself!");
return self;
}
- (void)testMethod
{
NSUInteger length = self.string.length;
length += [self.myself string].length;
length += self.innerMethod;
length += self.theValue;
NSLog(@"length = %tu", length);
}
- (int)innerMethod
{
return 100;
}
- (int)theValue
{
return 10;
}
@end
int main(void)
{
NSAutoreleasePool *pool = NSAutoreleasePool.new;
MyObject *obj = MyObject.new;
obj.string = @"Hello, world!";
[obj testMethod];
NSLog(@"The class method content is: %@", MyObject.classMethod);
// 由于classMethod類方法返回的是id類型哥捕,
// 因此這里不能直接使用[MyObject.classMethod length]這種調(diào)用方式。
// 不過以下兩種方式卻都沒問題嘉熊。
NSLog(@"The length is: %tu", [(NSString*)MyObject.classMethod length]);
NSLog(@"The length is: %tu", [[MyObject classMethod] length]);
[obj release];
[pool drain];
}
上述代碼簡(jiǎn)潔扼要地列出了大家在基于GCC編譯器進(jìn)行編寫Objective-C時(shí)所需要注意的點(diǎn)遥赚。