掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
本隨筆系列主要介紹從一個(gè)Windows平臺(tái)從事C#開(kāi)發(fā)到Mac平臺(tái)開(kāi)發(fā)蘋(píng)果開(kāi)發(fā)的一系列感想和體驗(yàn)歷程,本系列文章是在起步階段逐步積累的,希望帶給大家更好,更真實(shí)的轉(zhuǎn)換歷程體驗(yàn)。

站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到立山網(wǎng)站設(shè)計(jì)與立山網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類(lèi)型包括:成都網(wǎng)站制作、成都做網(wǎng)站、外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、國(guó)際域名空間、雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋立山地區(qū)。
在上篇《從C#到Object C,循序漸進(jìn)學(xué)習(xí)蘋(píng)果開(kāi)發(fā)(1)--準(zhǔn)備開(kāi)發(fā)賬號(hào)和開(kāi)發(fā)環(huán)境》介紹了一些基本的轉(zhuǎn)換感悟和一些基礎(chǔ)的準(zhǔn)備工作,還沒(méi)有正式真實(shí)的介紹Object C和C#的之前差異,我們知道,從一種環(huán)境或者一種語(yǔ)言轉(zhuǎn)換過(guò)去另外一種,我們都會(huì)做一些對(duì)比和理解,這樣可以很容易把我們頭腦的知識(shí)進(jìn)行對(duì)接,在這個(gè)所有東西日益大同的背景下,我們相信,所有的語(yǔ)言特點(diǎn)都是相通的。
1、面向?qū)ο蟮念?lèi)
1)類(lèi)的定義
Object C(下稱(chēng)OC)和C#都是面向?qū)ο蟮恼Z(yǔ)言,雖然OC比C#古老,起源自C,但是很多特點(diǎn)和C#都很接近了,在C#3.0里面才引入的擴(kuò)展方法,在OC里面也存在了。
OC和C#都一樣,他們繼承的關(guān)系都是單繼承的,沒(méi)有C++的那種多重繼承那么復(fù)雜,OC很有特點(diǎn)的一個(gè)要求就是把接口和實(shí)現(xiàn)完全分開(kāi),這點(diǎn)是熟悉C#開(kāi)發(fā)的人員必須轉(zhuǎn)換過(guò)來(lái)的思路,在OC里面,寫(xiě)一個(gè)類(lèi),先寫(xiě)接口定義,然后再寫(xiě)實(shí)現(xiàn),它的語(yǔ)法和C#很大不同,但是也很容易理解。
OC的關(guān)鍵字一般都是以@符號(hào)進(jìn)行標(biāo)識(shí),這點(diǎn)和C#的默認(rèn)保留關(guān)鍵字不同,一般看到@interface, @property, @關(guān)鍵字,在最新版本的XCode里面,真是發(fā)揮到了極致了,包含了很多語(yǔ)法糖,基本上和C#走向了大同,這點(diǎn)在對(duì)象的初始化繼續(xù)介紹。
OC的類(lèi)定義放到.h文件里面,實(shí)現(xiàn)放到了.m文件里面,如下面是類(lèi)的接口聲明。
- @interface SimpleClass : NSObject
- @end
而類(lèi)的實(shí)現(xiàn)操作如下所示。
- #import "SimpleClass.h"
- @implementation SimpleClass
- @end
上面只是一個(gè)演示類(lèi)的概念,一般情況下,類(lèi)都有屬性或者方法,因此還需要增加很多東西。
另外OC和C#對(duì)比,沒(méi)有了命名空間的概念,OC的類(lèi)為了避免混淆一般通過(guò)前綴進(jìn)行區(qū)分,如你看到的IOS基礎(chǔ)類(lèi)庫(kù),很多帶有NS,UI,CA,等這樣的前綴,就是這個(gè)原因。
2)方法的定義
如下面的接口聲明一個(gè)方法,方法的定義
- @interface XYZPerson : NSObject
- - (void)sayHello;
- @end
我們看到,上面的方法定義(接口定義)很簡(jiǎn)單,這里有一個(gè) - 符號(hào),是用來(lái)標(biāo)識(shí)屬于實(shí)例方法的,還有一種屬于類(lèi)級(jí)別的方法,用+符號(hào)標(biāo)識(shí),這個(gè)加號(hào),類(lèi)似于C#語(yǔ)言里面的static關(guān)鍵字,默認(rèn)在方法定義為-的實(shí)例方法,都是類(lèi)似于C#里面的public方法了。
這個(gè)(void)定義是返回值的標(biāo)識(shí),C#是不需要括號(hào)的void標(biāo)識(shí)無(wú)返回值,方法最后需要括號(hào)標(biāo)識(shí)。
- (void)sayHello;
這個(gè)方法的定義沒(méi)有參數(shù)因此是這樣寫(xiě)的,如果方法有多個(gè)參數(shù),這個(gè)OC就很有意思,我感覺(jué)這個(gè)是OC里面最有個(gè)性的一個(gè)地方了。
如果方法如下所示:
- (void) setCaption: (NSString*)input;
類(lèi)方法的調(diào)用是通過(guò)空格,而C#通過(guò)點(diǎn)進(jìn)行調(diào)用,這點(diǎn)也有所不同,OC通過(guò)在一個(gè)[]里面空格進(jìn)行引用,如下所示。
- [object method];
- [object methodWithInput:input];
剛才定義的sayHello方法,它的調(diào)用可能就是如下方式了
[self setCaption:@"Default Caption"];
如果方法的定義為多個(gè)參數(shù)(也叫多重參數(shù)),定義如下。
-(void) setNumerator: (int) n andDenominator: (int) d;
那么方法的調(diào)用就很有意思了。
[frac2 setNumerator: 1 andDenominator: 5];
如果還有更多的參數(shù),那么也就一直使用這樣的累加方式,這個(gè)有點(diǎn)接近閱讀習(xí)慣,呵呵。
3)參數(shù)的定義
說(shuō)完方法的定義和使用,我們介紹下類(lèi)里面的屬性的定義,我們知道C#里面的屬性定義很簡(jiǎn)單了,如
- public string Name {get;set;}
回來(lái)看看OC如何定義屬性的,一般在.h的接口定義里,可以這樣定義。
- @property NSString *firstName;
- @property NSString *lastName;
然后在實(shí)現(xiàn)類(lèi)代碼里面,添加它的對(duì)應(yīng)代碼@synthesize的關(guān)鍵字
- @synthesize firstName, lastName;
屬性當(dāng)然也可以指定為只讀的,如下代碼所示
- @property (readonly) NSString *fullName;
另外,我們還需要清楚,屬性默認(rèn)是線程安全的,也就是atomic,還有它是強(qiáng)類(lèi)型Strong的。
- @interface XYZObject : NSObject
- @property NSObject *implicitAtomicObject; // atomic by default
- @property (atomic) NSObject *explicitAtomicObject; // explicitly marked atomic
- @end
在很多地方,我們使用屬性的時(shí)候,都不需要指定它的線程安全特性,因?yàn)槟菢有矢?,一般的屬性定義代碼如下所示。
- @property (strong, nonatomic) IBOutlet UILabel *lblName;
- @property (strong, nonatomic) IBOutlet UITextField *txtInput;
至于是不是所有的屬性都應(yīng)該指定為Strong,這個(gè)肯定不是的,strong的另外一種類(lèi)型是weak,它是表示弱類(lèi)型,強(qiáng)類(lèi)型和弱類(lèi)型主要是針對(duì)ARC來(lái)說(shuō)的,它是引用計(jì)數(shù)的范疇,Strong相當(dāng)于原來(lái)的retain。
一般情況下,為了避免一些強(qiáng)類(lèi)型的對(duì)象屬性導(dǎo)致出現(xiàn)相互引用的問(wèn)題,在代理類(lèi)和數(shù)據(jù)源對(duì)象,還有一些如UITable的對(duì)象屬性,他們的屬性定義必須指定為weak的。
#p#
2、對(duì)象的類(lèi)型和初始化工作
在C#里面,我們知道,它里面包含了有一些基本類(lèi)型(Primitive type)和一些包裝后的對(duì)象類(lèi)型,如它的基本類(lèi)型包括string int char float long double decimal等等,它的對(duì)應(yīng)包裝類(lèi)型有String Int32 Char Single Int64 Double Decimal等等。
在OC里面,同樣也有這樣的情況,OC的基本類(lèi)型繼承自C語(yǔ)言的基礎(chǔ)類(lèi)型,包括有int float double char 等基礎(chǔ)類(lèi)型,也有很多NS開(kāi)頭的引用類(lèi)型(或者說(shuō)包裝類(lèi)型),如NSString NSNumber NSDate NSData NSValue等等,而很多集合類(lèi)型NSArray NSMutableArray NSDictionary等都需要添加引用類(lèi)型的對(duì)象。
另外和C#的Object對(duì)象類(lèi)似或者動(dòng)態(tài)類(lèi)型關(guān)鍵字dynamic指定的類(lèi)型一樣,OC里面包含了一個(gè)id的類(lèi)型,這個(gè)是一個(gè)不確定的類(lèi)型,它可以看成是一個(gè)任何類(lèi)型的弱定義。
id類(lèi)型是一個(gè)獨(dú)特的數(shù)據(jù)類(lèi)型,在概念上,類(lèi)似java的Object類(lèi),可以轉(zhuǎn)換為任何數(shù)據(jù)類(lèi)型。換句話說(shuō),id類(lèi)型變量可以存放任何數(shù)據(jù)類(lèi)型的對(duì)象。在內(nèi)部處理上,這種類(lèi)型被定義為指向?qū)ο蟮闹羔?,?shí)際上是一個(gè)指向這種對(duì)象的實(shí)例變量的指針。需要注意的是id是一個(gè)指針,所以在使用id的時(shí)候不需要加星號(hào);比如說(shuō):id foo=nil;
1)類(lèi)對(duì)象的初始化
我們知道,OC里面很多都是通過(guò)alloc init這樣的方式進(jìn)行初始化,如下面代碼所示。
- XYZObject *object = [[XYZObject alloc] init];
而C#里面大多數(shù)使用new方式進(jìn)行初始化,其實(shí)OC里面,也一樣可以通過(guò)new方式進(jìn)行初始化,不過(guò)僅限在默認(rèn)構(gòu)造函數(shù)的方式進(jìn)行,如下的代碼是等同于上面的語(yǔ)句的。
- XYZObject *object = [XYZObject new];
不過(guò)好像很多人都習(xí)慣用第一種方式初始化對(duì)象。
2)字符串的初始化
相信很多人使用OC的時(shí)候,第一個(gè)印象最深的我覺(jué)得可能是NSString類(lèi)了,這個(gè)是和C#的String有點(diǎn)類(lèi)似,都是固定的字符串對(duì)象,如果需要變化類(lèi)型的字符串對(duì)象,C#里面是可以使用StringBuilder,而OC里面可以使用NSMutalbeString,NSMutableString好比一個(gè)字符串鏈表,它可以任意的動(dòng)態(tài)在字符串中添加字符串 刪除字符串 指定位置插入字符串,使用它來(lái)操作字符串會(huì)更加靈活。
字符串的定義和初始化和簡(jiǎn)單,我們可以通過(guò)下面的方式進(jìn)行初始化。
- NSString *someString = @"Hello, World!";
我們知道,C#也可以使用@字符進(jìn)行賦值,雖然一般情況使用在多行的情況下,但是在OC,這個(gè)@字符不能省略。
其他數(shù)據(jù)類(lèi)型初始化,很多都依靠@字符進(jìn)行,這個(gè)@字符可以說(shuō)是非常強(qiáng)大的,它也可以說(shuō)是一個(gè)很好的語(yǔ)法糖,如下面初始化各種類(lèi)型的代碼如下(在OC里面,NSNumber可以放置任何引用類(lèi)型)
- NSNumber *myBOOL = @YES;
- NSNumber *myFloat = @3.14f;
- NSNumber *myInt = @42;
- NSNumber *myLong = @42L;
NSNumber類(lèi)型可以裝納各種類(lèi)型,同樣它也可以轉(zhuǎn)換為其他對(duì)應(yīng)的類(lèi)型,如下代碼所示
- int scalarMagic = [magicNumber intValue];
- unsigned int scalarUnsigned = [unsignedNumber unsignedIntValue];
- long scalarLong = [longNumber longValue];
- BOOL scalarBool = [boolNumber boolValue];
- float scalarSimpleFloat = [simpleFloat floatValue];
- double scalarBetterDouble = [betterDouble doubleValue];
- char scalarChar = [someChar charValue];
另外,由于OC里面引入了一個(gè)id類(lèi)型,可以認(rèn)為它的作用和C# 3.0引入的動(dòng)態(tài)類(lèi)型相當(dāng),它可以在運(yùn)行時(shí)進(jìn)行確定對(duì)象是否具有某個(gè)方法,而不會(huì)在編譯的時(shí)候強(qiáng)制指定。
如下面的代碼編譯通過(guò),運(yùn)行的時(shí)候可能出錯(cuò)。
- id someObject = @"Hello, World!";
- [someObject removeAllObjects];
之所以編譯的時(shí)候,不檢查它的對(duì)象是否有removeAllObject接口方法,是因?yàn)檫@兒的someObjec指定為了id的動(dòng)態(tài)類(lèi)型,所以編譯器會(huì)不檢查它的方法。
3)對(duì)象集合的初始化
剛才上面介紹了字符串等各種類(lèi)型的初始化,很多采用了強(qiáng)大的關(guān)鍵字@進(jìn)行初始化,這個(gè)語(yǔ)法糖減少了很多繁瑣的方法調(diào)用,對(duì)于集合的初始化,尤其這樣。
如果按照傳統(tǒng)的集合定義方式,一般是通過(guò)下面的方法。
- NSArray *someArray =
- [NSArray arrayWithObjects:someObject, someString, someNumber, someValue, nil];
在里面的集合,最后必須加上一個(gè)nil的東西,這個(gè)在C#的領(lǐng)域里面是不需要增加這樣的標(biāo)識(shí)的,在Object C里面,如果你要通過(guò)arrayWithObjects方法進(jìn)行構(gòu)造,必須增加一個(gè)這樣的東西,告訴它這個(gè)是最后了,如果你把這個(gè)放到第二位,那么構(gòu)造的集合也只有兩個(gè)對(duì)象了,很奇怪了。
如果采用了強(qiáng)大的@方法構(gòu)造,一切都和C#相似了,這里你只能佩服它的神奇之處了。
- NSArray *someArray = @[firstObject, secondObject, thirdObject];
如下面定義一個(gè)字符串的集合是這樣的。
- NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
在C#里面,我們經(jīng)常用到了字典對(duì)象,這個(gè)對(duì)象非常方便。當(dāng)然在OC里面,也肯定會(huì)有這樣的東西,畢竟很多語(yǔ)言都會(huì)支持的。
這個(gè)字典類(lèi)型也是一個(gè)集合類(lèi)型,它的傳統(tǒng)構(gòu)造方法如下所示
- NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
- someObject, @"anObject",
- @"Hello, World!", @"helloString",
- @42, @"magicNumber",
- someValue, @"aValue",
- nil];
它這個(gè)看起來(lái)很怪異,添加指點(diǎn)是按照object,key的這樣方式添加的,這個(gè)與我們使用C#的習(xí)慣有很大的不同哦,而且最后還帶了一個(gè)nil的尾巴。
如果采用@構(gòu)造函數(shù),一切又都清凈了,已經(jīng)是key,value方式進(jìn)行存儲(chǔ),而且不用nil了,如果你添加了nil,那么會(huì)出錯(cuò)的。
- NSDictionary *dictionary = @{
- @"anObject" : someObject,
- @"helloString" : @"Hello, World!",
- @"magicNumber" : @42,
- @"aValue" : someValue
- };
集合中,如果取某個(gè)對(duì)象,那么通過(guò)下面的方法進(jìn)行獲取
- NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"];
也可以通過(guò)下標(biāo)括符進(jìn)行獲取
- NSNumber *storedNumber = dictionary[@"magicNumber"];
如果是一般的數(shù)組集合,可以通過(guò)下面方式獲取,這種方式和c#很類(lèi)似了。
- NSNumber *storedNumber = array[0];
由于時(shí)間和篇幅的問(wèn)題,關(guān)于OC的各種和C#對(duì)比的特性,以后繼續(xù)介紹,OC里面還涉及很多相關(guān)的特點(diǎn),如擴(kuò)展方法,協(xié)議(類(lèi)似接口),代碼塊等等內(nèi)容,以及XCode的各種使用特性,有空繼續(xù)介紹。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流