Swift與Objective-C的簡(jiǎn)單校對(duì)

最近的瑣事

最近在處理Swift 版本遷移所引發(fā)的一些問題,引起了我的注意!
在xCode 8.3.2中,已經(jīng)不能再次編譯Swift2.3了,所以所有的swift2.3 項(xiàng)目都要遷移到3.1。真心碎......
在之前我已經(jīng)用swift3.0寫過另一個(gè)關(guān)于項(xiàng)目,但是改動(dòng)起來還是賊煩,慢慢改吧。
無可否認(rèn),swift的開發(fā)速度的確會(huì)比傳統(tǒng)的Objective-C快許多,畢竟簡(jiǎn)化了內(nèi)容,優(yōu)化了性能。
此次,我還需要使用Objective-C來重寫一個(gè)之前用swift寫的項(xiàng)目,所以幾天下來,項(xiàng)目沒寫完,反而寫下了這篇牢騷文章。

在一個(gè)簡(jiǎn)單的賦值修改的問題上,在Objective-C上我使用了下面的方法組織了一波數(shù)據(jù):

NSDictionary *dict1 = @{@"title":@"123456",@"image":@"aux_task"}; 
[_collectionArray addObject:dict1];

然后在我需要在后續(xù)的添加、或修改的時(shí)候:

_collectionArray[0][@"image"] = @"light_task_selected";

就會(huì)出現(xiàn)下面的情況

-[__NSCFNumber setObject:forKeyedSubscript:]: 
unrecognized selector sent to instance 0xb000000000000002
2017-04-24 16:31:30.589128+0800 BleMate2[1603:771672]
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException',
 reason: '-[__NSCFNumber setObject:forKeyedSubscript:]: unrecognized selector sent to instance 0xb000000000000002'

????
WTF?!
原因在于Objective-C是引用類型語法,在往Array里面input對(duì)象dict的時(shí)候,其實(shí)是它的整個(gè)對(duì)象的屬性也放進(jìn)去了,也就是說,如果是不允許修改的屬性放進(jìn)去了,還是一樣不能修改!
于是可以通過這樣的方式進(jìn)行寫入即可在后來繼續(xù)修改:

  NSMutableDictionary *dict = [NSMutableDictionary dictionary];  
 [dict setValue:@"123456" forKey:@"title"];  
 [dict setValue:@"bt_task" forKey:@"image"];
 [_collectionArray addObject:dict];
 _collectionArray[0][@"image"] = @"light_task_selected";

而swift對(duì)于這些就變得簡(jiǎn)單了,它采用了復(fù)制結(jié)構(gòu)體的方式,也就是說當(dāng)你丟進(jìn)去的是這樣的內(nèi)容:

//先定一個(gè)結(jié)構(gòu)體
struct AboutItemInfo {     
   var titleName:String  
   var image:UIImage
}?
//然后定義一個(gè)值,并賦值
let aboutArray:[AboutItemInfo]! = []
let item = AboutItemInfo.init(titleName:"nihao",image:#imageLiteral(resourceName: "heart_rate"))?aboutArray.append(item)

?//隨后如果想對(duì)其內(nèi)容進(jìn)行修改,只需要直接讀出來修改即可
aboutArray[0].titleName = "nihuai"

為什么會(huì)可以這樣呢?!
因?yàn)槭菑?fù)制的方式進(jìn)行的運(yùn)行方式,所以aboutArray里面的對(duì)象,其實(shí)已經(jīng)在傳進(jìn)去的過程中就被復(fù)制到AboutArray里面,當(dāng)再次讀取修改的時(shí)候,是對(duì)AboutArray里面的值進(jìn)行修改。
我想有可能是因?yàn)镺bjective-C使用了別的方法去代替類似于上面的那種做法。于是我去翻了翻遠(yuǎn)古時(shí)代的Objective-C 結(jié)構(gòu)體

typedef struct Book{
    NSString *name; 
   NSString *Author; 
   int     book_id;
} book;

但是把字敲到xCode上就發(fā)現(xiàn)它提示了一個(gè)錯(cuò)誤:ARC forbids Objective-C objects in Struct
突然意識(shí)到在自動(dòng)釋放之后,這些東西會(huì)變得不靠譜,因?yàn)槿绻浑S之釋放就會(huì)造成內(nèi)存溢出,所以針對(duì)以上的問題,可以把它變成手動(dòng)釋放后嘗試了一下。終于成功了?。ǖ杏X好像倒退了十幾年.....)
雖然官方也給出了關(guān)于ARC之后的這種類型結(jié)構(gòu)體最好交給類來解決,但是相對(duì)于Swift的輕便,也顯得過于臃腫了。然后細(xì)心的想了下,為什么Swift在各大測(cè)評(píng)平臺(tái)上總是比Objective-C跑得快?!

管中規(guī)豹

就當(dāng)前所遇到的問題,完全可以歸類為結(jié)構(gòu)體和類之間的戰(zhàn)爭(zhēng)!
在swift中,包括許多的基本類型,諸如String,Array還有Dictionary等類型都是以結(jié)構(gòu)體的形式實(shí)現(xiàn),這意味著被賦值給新的常量或變量,或者在這些基本類型被傳入到函數(shù)或方法中的時(shí)候,他們的值是會(huì)被copy的。
而在Objective-C中,NSString,NSArray、NSDictionary類型都是作為類的形式實(shí)現(xiàn),而并非結(jié)構(gòu)體,他們?cè)诒毁x值的時(shí)候、被傳入函數(shù)或方法的時(shí)候,它們不會(huì)被拷貝,而是傳遞了現(xiàn)有實(shí)例的引用。
具體可以參考下面這個(gè)例子:

//在Objective-C中,使用下面的方式進(jìn)行國(guó)際多語言化
_headTitleLab.text = NSLocalizedString(@"BLEConnect_Ble", @"");
?//當(dāng)應(yīng)用內(nèi)發(fā)生了語言設(shè)置的變更
[NSBundle setLanguage:"en"];?
//那么_headTitleLab就會(huì)顯示成別的語言的了,不需要重新賦值?

那么如果在swift中做出同樣的操作則需要重新對(duì)其進(jìn)行取值賦值的操作,不然就會(huì)不刷新語言。

////在Swift中,使用下面的方式進(jìn)行國(guó)際多語言化
headTitleLab.text = NSLocalizedString("BLEConnect_Ble", comment: "")
//當(dāng)應(yīng)用內(nèi)發(fā)生了語言設(shè)置的變更
Bundle.setLanguage("en")
//如果想應(yīng)用內(nèi)的語言隨之變更,就需要重新進(jìn)行賦值才會(huì)成功
headTitleLab.text = NSLocalizedString("BLEConnect_Ble", comment: "")

另外值得一提的是:
以上是對(duì)字符串、數(shù)組、字典的“拷貝”行為的描述。在你的代碼中,拷貝行為看起來似乎總會(huì)發(fā)生。然而,Swift 在幕后只在絕對(duì)必要時(shí)才執(zhí)行實(shí)際的拷貝。Swift 管理所有的值拷貝以確保性能最優(yōu)化,所以你沒必要去回避賦值來保證性能最優(yōu)化。
而Objective-C的做法是,先實(shí)例化了類,然后才做數(shù)據(jù)存儲(chǔ)處理,所以在這里性能也是大打折扣的地方。
這里讓我感覺swift其實(shí)是一個(gè)結(jié)構(gòu)體語言,而Objective-C則是引用類的語言,現(xiàn)在想來結(jié)構(gòu)體的簡(jiǎn)單賦值方式的確有利于運(yùn)行速度。

另外翻看他們的編譯器CLange的編譯過程時(shí),發(fā)現(xiàn)因?yàn)?swift 在編譯時(shí)就完成了方法綁定直接通過地址調(diào)用屬于強(qiáng)類型語言,方法調(diào)用不再是像Objective-C那樣的消息發(fā)送,這樣編譯就可以獲得更多的信息用在后面的后端優(yōu)化上了,其實(shí)這樣也加快的Swift的運(yùn)行速度。

這里很想深入的探討swift的閉包較Objective-C的Block如何,進(jìn)行深入的研究,無奈對(duì)swift的閉包理解還是比較欠缺,還得深入的了解一番才可以有內(nèi)容所寫。

寫在最后

今天也看到王先生的文章,應(yīng)當(dāng)理解為科技和開發(fā)手段是不斷進(jìn)步和優(yōu)化的,但是解決問題,還是要從實(shí)際出發(fā)。畢竟,我們的存在只是為了解決問題。關(guān)于Objective-C和Swift也一樣,其實(shí)Objective-C穩(wěn)定的當(dāng)了那么多年的老大哥,還是有一定的可取之處的。

另外,還是關(guān)于swift和Objective-C到底應(yīng)該用什么語言進(jìn)行開發(fā),這種事情還真不好說了!如果有的選,我還是選Swift吧!當(dāng)然了要在開發(fā)的流程成熟的團(tuán)隊(duì)才可以讓Swift飛起來。

越來越發(fā)現(xiàn)xCode在開發(fā)的時(shí)候所提示的警告都是重要的,因?yàn)槟悴恢朗裁磿r(shí)候就突然不被兼容了!


本文參考:
極客學(xué)堂
老王_人生導(dǎo)師

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容