原創(chuàng)|使用教程|編輯:龔雪|2014-06-19 10:36:23.000|閱讀 1004 次
概述:初次接觸Swift總會有不少問題,比如剛?cè)胄械拈_發(fā)者應(yīng)該學(xué)習(xí)Objective-C還是Swift?有沒有Swift可以實(shí)現(xiàn),但Objective-C不能實(shí)現(xiàn)的事情?以及能否用Swift來調(diào)用自己的Objective-C代碼或者第三方庫等等。下面這篇文章針對這些問題進(jìn)行了解答。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
作為蘋果在WWDC 2014上發(fā)布的新編程語言,Swift絕對是當(dāng)前的熱門話題。Swift由蘋果開發(fā)者工具部門總監(jiān)克里斯·拉特納(Chris Lattner)耗時四年開發(fā)而成,蘋果宣稱Swift的特點(diǎn)是:快速、現(xiàn)代、安全、互動,且全面優(yōu)于Objective-C語言。
在Swift發(fā)布之后,隨之而來的便是各種入門教程,各種上手體驗(yàn),各種用Swift編寫的demo...不管是經(jīng)驗(yàn)豐富的開發(fā)者還是新手開發(fā)者都急切地想上手體驗(yàn)下這門汲取了Objective-C、Rust、Haskell、Ruby、Python、C#以及CLU等編程語言精華的新語言。不過,初次接觸Swift總會有不少問題,比如剛?cè)胄械拈_發(fā)者應(yīng)該學(xué)習(xí)Objective-C還是Swift?有沒有Swift可以實(shí)現(xiàn),但Objective-C不能實(shí)現(xiàn)的事情?以及能否用Swift來調(diào)用自己的Objective-C代碼或者第三方庫等等。下面這篇文章針對這些問題進(jìn)行了解答。
基礎(chǔ)部分
1、我是個剛?cè)胄械拈_發(fā)者,我應(yīng)該學(xué)習(xí)Objective-C還是Swift,還是兩個都學(xué)?
這取決于你是計(jì)劃到其他公司工作,還是作為一個獨(dú)立iOS開發(fā)者。
a. 如果你是其他公司的全職iOS開發(fā)者或者顧問,你最好兩個都學(xué)。因?yàn)楹芏?公司現(xiàn)有的代碼還是用Objective-C寫的,你需要理解這些代碼。并且一些公司不會立刻過渡到Swift語言開發(fā)。此外,你還需要理解使用Objective-C編寫的海量iOS庫、教程以及示例項(xiàng)目。另外,隨著時間的推移,很多公司會逐漸過渡到Swift開發(fā),所以你也需要學(xué)習(xí)Swift。
b. 如果你是獨(dú)立開發(fā)者,你打算從一開始就使用Swift,理論上你只了解Swift就可以了。但如果你有時間,還是應(yīng)該去了解Objective-C,這樣你就可以使用已有的Objective-C強(qiáng)大的資源庫。
根據(jù)市場的變化和Swift滲透率的增長,這個問題的答案也在不斷變化。最終,知道Objective-C可能會像知道COBOL一樣了。
2、我有多年的Objective-C開發(fā)經(jīng)驗(yàn)。對于Swift,我是新手么?
是,但也不是。如果你為蘋果平臺開發(fā)過一段時間,你仍有很大的優(yōu)勢。因?yàn)槟愫苁煜code和Cocoa/Cocoa Touch API。學(xué)習(xí)Xcode和上千個Cocoa/Cocoa Touch API要比學(xué)Swift花的時間更長,所以你有很好的開發(fā)基礎(chǔ)。長話短說,一旦你熟悉了Swift代碼,你就能很快地學(xué)習(xí)Swift。
3、iOS 8和OS X Yosemite的應(yīng)用程序只使用Swift語言么?
不是。Swift語言能與Objective-C流暢地交互,反之亦然。蘋果并沒有完全將Objective-C 的API轉(zhuǎn)成Swift,但你仍可以在Swift代碼中仍使用這些API。時間會證明一切,但是很多年內(nèi)iOS和OS X商店在采用Swift語言的同時仍會繼續(xù)依賴Objective-C語言。
4、Swift語言適用于其他版本的iOS和OS X系統(tǒng)么?
是的!Xcode 6可以為iOS 7及以上和OS X10.9及以上的系統(tǒng)版本編譯Swift代碼。其實(shí),現(xiàn)在你從App Store下載的WWDC app就是蘋果用Swift語言編寫的。
但是,記住蘋果不允許使用Xcode Beta版本創(chuàng)建的應(yīng)用程序提交到App Store。因此,你需要等到Xcode 6正式版發(fā)布才能在App Store中上傳Swift編寫的應(yīng)用程序。
5、.Swift語言是取代Objective-C,還是對其的補(bǔ)充?
引用蘋果官方的一句話,“Objective-C不會消失,Swift和Objective-C可同時用于Cocoa和CocoaTouch開發(fā)。”因此,你仍然可以繼續(xù)使用Objective-C。然而,蘋果似乎鼓勵你使用Swift進(jìn)行新的開發(fā),而不是希望你重寫所有的Objective-C代碼。我們猜測蘋果在未來的框架和API開發(fā)中將會逐漸減少使用Objective-C語言,甚至有一天會棄用Objective-C,所以早作準(zhǔn)備吧!
6、playground是什么?
playground是一個文件,你可以編寫代碼的同時即刻看到運(yùn)行效果。對于學(xué)習(xí)Swift或者新的API、原型代碼或者算法真的很有用處!
7、如何學(xué)習(xí)Swift?
網(wǎng)上已經(jīng)有很多不錯的資源:
蘋果的
你也可以在Xcode中閱讀本書:Help\Documentation and API Reference\New Features in Xcode 6 Beta\Swift Language\The Swift Programming Language\A Swift Tour\Open Playground)
我們的 和
8、未來你們的書和教程會使用Swift嗎?
會的。我們會幫開發(fā)者過渡到Swift。
進(jìn)階
1、有沒有Swift可以實(shí)現(xiàn),但Objective-C不能實(shí)現(xiàn)的事情?或者反過來說。
是的。Swift是一門現(xiàn)代語言,引入了很多Objective-C不支持的內(nèi)容。比如命名空間(namspacing)、可選類型(optionals)、元組(tuples)、泛型(generics),類型推斷(type inference)以及其他等等。當(dāng)然,Objective-C也有一些Swift不具備的特性,比如messaging nil.
想了解更多細(xì)節(jié),建議在讀完本文后閱讀下蘋果的官方文檔: (這里有 )
2、有沒有Swift不能用的API?
在寫這篇文章時,我還沒發(fā)現(xiàn)有。但在使用Objective-C和Swift互通方面有些注意事項(xiàng):
a. 當(dāng)一個Objective-C的API返回一個id時,Swift將接收到AnyObject。
b. 當(dāng)一個Objective-C API返回nil,Swift將獲得一組Optional類型的值,且被設(shè)置成NONE,Swift以這種方式來表示一個變量為nil。Swift的變量必須始終包含一個值,因?yàn)椴荒鼙WCObjective-C 方法不會返回nil,所以Swift使用Optional類型枚舉來保存任何從Objective-C API返回的對象。
c. 當(dāng)一個Objective-C API返回一個集合時,由于Swift無法判斷NSArray或NSDictionary存儲了什么類型,所以它會被轉(zhuǎn)換為AnyObject 。基于你對API的了解,向下轉(zhuǎn)換(downcast)你的集合是個很好的習(xí)慣。思考一個返回NSString實(shí)例的數(shù)組的Objective-C方法。由于你已經(jīng)知道返回的數(shù)組里包含了字符串,所以你可以像下邊那樣安全地進(jìn)行轉(zhuǎn)換:
let fruits : AnyObject[] = // some Objective-C API that returns NSArray of NSStrings for fruit in fruits as String[] { println(fruit) }
d. 當(dāng)一個Swift API返回一個元組(Tuple),Objective-C將收不到任何值。這是因?yàn)镺bjective-C不支持元組,因此該方法不適用于Objective-C代碼。以下是Objective-C不支持的類型:
· 泛型(Generics)
· 元組(Tuples)
· 在Swift中定義的枚舉(Enumerations defined in Swift)
· 在Swift中定義的結(jié)構(gòu)體(Structures defined in Swift)
· 在Swift中定義的頂級函數(shù)(Top-level functions defined in Swift)
· 在Swift中定義的全局變量(Global variables defined in Swift)
· 在Swift中定義的類型別名(Typealiases defined in Swift)
· Swift風(fēng)格的variadics(Swift-style variadics)
· 嵌套類型(Nested types)
· Curried 函數(shù)(Curried functions)
3、Playground中,println()結(jié)果在哪里?
你必須打開Assistant Editor才能看到控制臺輸出。步驟:View > Assistant Editor > Show Assistant Editor,或者使用快捷鍵: Option + Command + Return.(感謝的這個觀點(diǎn))
4、怎樣在Playgrounds中看到那些很酷的值的圖形?
你可以在Playgrounds里繪出值的結(jié)果,這對于可視化算法是很方便的。在playground里面輸入能夠產(chǎn)生值的代碼:
for x in 1..10 { x }
在側(cè)邊欄,你會看到類似于“9 times”的東西。把鼠標(biāo)移到這一行上,會出現(xiàn)“+”按鈕。點(diǎn)擊這個按鈕(并確保你打開了Assistant Editor),你將會看到圖形。
5、你如何運(yùn)行REPL?
在終端運(yùn)行以下命令,告訴它使用Xcode 6的命令行工具。
sudo xcode-select -s /Applications/Xcode6-Beta.app/Contents/Developer/
然后運(yùn)行以下代碼開始Swift REPL。
xcrun swift
如果準(zhǔn)備退出,你可以鍵入:exit或者:quit。你也可以使用CTRL+D快捷鍵。
6.你能用Swift來調(diào)用自己的Objective-C代碼或者第三方庫嗎?如果能,要怎么做呢?
可以!當(dāng)你往Xcode項(xiàng)目里添加第一個.swift文件時,系統(tǒng)會提示你讓Xcode創(chuàng)建一個橋接頭文件(bridging header file)。你可以在這個頭文件中導(dǎo)入你希望可見于Swift代碼的Objective-C頭文件。然后,所有的類無需導(dǎo)入都可為Swift所用,你可以使用和系統(tǒng)類相同的Swift語法來使用自定義Objective-C代碼。
7、那么,數(shù)組只能包含一個類型的對象嗎?如果我想要不同的類型呢?
在Swift中,強(qiáng)烈建議你使用只包含一種類型的強(qiáng)類型數(shù)組,語法像是:
var goodArray: String[] = [ "foo" , "bar" ]
也就是說,從技術(shù)上講,你依然可以創(chuàng)建包含多個類型對象的數(shù)組。但最好在做之前問問自己為什么想這么做。按照這種說法,你可以使用AnyObject:創(chuàng)建一個包含不同類型對象的Swift數(shù)組:
var brokenArray: AnyObject[] = [ "foo" , 1, 12.23, true ]
8、對于字典(dictionary)也是一樣嗎?字典也是強(qiáng)類型(strongly typed)的嗎?
是的,不過你依然可以用AnyObject來解決。對于字典來說,它里邊所有的值不是同一個類型也講得通。以下是用字典表示的從服務(wù)器端返回的一個JSON響應(yīng):
來看一個服務(wù)器JSON響應(yīng)的例子,用字典來表示:
var employee : Dictionary<String, AnyObject> = [ "FirstName" : "Larry" , "LastName" : "Rodgers" , "Salary" : 65_000.00]
這個字典有兩個String類型的鍵和一個Double值類型的鍵。雖然這是可行的,但可能的話你應(yīng)該創(chuàng)建一級類模型對象來表示數(shù)據(jù),而不是依賴字典。
具體細(xì)節(jié)
1、在Swift中有id的等價替代嗎?
有。像上邊提到的那樣,當(dāng)Objective-C API 返回id類型時,Swift使用AnyObject替換。AnyObject類型可以代表任何類類型的實(shí)例。另外也有Any可代表任何類型的實(shí)例(除了函數(shù)類型)。
2、如何在Swift中自省?(類似 if ([obj isKindOfClass:[Foo class]]) { … })
你可以使用is關(guān)鍵字檢查變量或者常量的類型。編譯器足夠聰明讓你知道使用is是多余的。由于Swift的類型安全機(jī)制,不大可能為同一個引用賦一個不同的類型。
var someValue : Any? someValue = "String" if someValue is String { println( "someValue is a String" ) } else { println( "someValue is something else" ) }
注意如果你想這么編寫的話...
var someValue = "String" if someValue is String { println( "someValue is a String" ) } else { println( "someValue is something else" ) }
你會收到一個編譯器警告:
Playground execution failed: error: <REPL>:7:14: error: 'is' test is always true if someValue is String {
3、如何在Swift的枚舉中存放位移值?(i.e. MyVal = 1<<5)
不幸的是蘋果尚未解決這個問題。不過有傳言稱他們正努力在這方面做的更好。按照這個說法,我們需要今天編寫代碼,對吧?以下是別人如何做到了這一點(diǎn)。
使用以下方案處理這個問題,你可以在 上查看更多細(xì)節(jié):
struct MyOptions : RawOptionSet { var value: UInt = 0 init(_ value: UInt) { self.value = value } func toRaw() -> UInt { return self.value } func getLogicValue() -> Bool { return self.value != 0 } static func fromRaw(raw: UInt) -> MyOptions? { return MyOptions(raw) } static func fromMask(raw: UInt) -> MyOptions { return MyOptions(raw) } static var None: MyOptions { return MyOptions(0) } static var FirstOption: MyOptions { return MyOptions(1 << 0) } static var SecondOption: MyOptions { return MyOptions(1 << 1) } static var ThirdOption: MyOptions { return MyOptions(1 << 2) } } func == (lhs: MyOptions, rhs: MyOptions) -> Bool { return lhs.value == rhs.value } func | (lhs: MyOptions, rhs: MyOptions) -> MyOptions { return MyOptions(lhs.value | rhs.value) } func & (lhs: MyOptions, rhs: MyOptions) -> MyOptions { return MyOptions(lhs.value & rhs.value) } func ^ (lhs: MyOptions, rhs: MyOptions) -> MyOptions { return MyOptions(lhs.value ^ rhs.value) }
教程組成員 想到了下邊更簡單的方法,你可以在他的 里 閱讀更多內(nèi)容。
class MyOptions { class var None : UInt32 { return 0 } class var All : UInt32 { return UInt32.max } class var First : UInt32 { return 1 } class var Second : UInt32 { return 1<<1 } class var Third : UInt32 { return 1<<2 } }
范例用法
physicsBody.categoryBitMask = MyOptions.First physcisBody.collisionBitMask = MyOptions.First | MyOptions.Second
Dave Lawson也寫了一篇你可能感興趣的文章:
以上是幾則相關(guān)的處理方法,不過希望蘋果在以后的版本中會解決這個問題。
4、Swift如何和Grand Central Dispatch一起使用?
同樣的方法,你可以像在Objective-C中那樣使用C API.在處理并發(fā)性時,你也可以使用蘋果高級NSOperationQueue。
5、Objective-C中的國際化宏命令呢?
類似Objective-C中的NSLocalizedString,你可以在Swift中使用NSLocalizedString(key:tableName:bundle:value:comment:) 方法為國際化做準(zhǔn)備。tableName、bundle以及value arguments都有默認(rèn)值,所以如果你正使用NSLocalizedString,你可以編寫如下代碼:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), { println( "test" ) });
6、我需要擔(dān)心引用生命周期嗎?
當(dāng)然!當(dāng)兩個對象彼此之間是強(qiáng)引用時,仍能創(chuàng)建一個retain cycle。你可以使用Objective-C中一樣的方法break這個retain cycle。有三個關(guān)鍵字用于聲明引用類型,詳情如下,弱引用和無主引用將解決你的引用生命周期問題。
何時應(yīng)該使用強(qiáng)引用、弱引用以及無主引用呢?
強(qiáng)引用:強(qiáng)引用會使得ARC保留實(shí)例直到不再需要它們。當(dāng)移除所有強(qiáng)引用時,引用實(shí)例就會被釋放。注意默認(rèn)情況下強(qiáng)引用是隱式的, 所以你不必顯式地聲明它。
弱引用:你應(yīng)該在獨(dú)立生命周期的對象間使用弱引用。當(dāng)為一個對象設(shè)置弱引用時,如果出于內(nèi)存壓力釋放了對象,表示你不介意這一點(diǎn)。弱引用的值必須是一個變量,使用var定義 ,并且必須是使用?運(yùn)算符的Optional類型。由于弱引用是可選的,所以你決不能以一個已經(jīng)不存在的無效實(shí)例的引用來結(jié)束。當(dāng)引用實(shí)例被釋放時,ARC將會自動把引用設(shè) 置為nil。
無主引用:你應(yīng)該為有相同生命周期的對象使用無主引用;比如當(dāng)一個對象指向其自身,以及你希望避免一個retain cycle。無論何時只要引用有一個值就可以使用無主引用,但當(dāng)你需要告訴ARC不要將它設(shè)置為nil時。無主引用的行為類似于Objective-C的unsafe_unretained。你要確保你不會在引用對象被釋放后訪問引用,這樣會導(dǎo)致你的 app崩潰。無主引用不能是可選的,不能被設(shè)置為nil。無主引用也是隱式解析。
分號去哪里了?
分號在Swift中是可選的,不過出于易讀性的目的,蘋果建議你不要再使用分號了。但有時候仍會在Swift中使用分號,比如在循環(huán)語句中。
下一步做什么?
這僅僅是版本1,蘋果的目的非常清楚,他們將在該語言上進(jìn)行迭代,所以你可以向蘋果報告bug,要求新特性等等。在該版本正式發(fā)布之前,仍有很大的提升空間。
CocoaPods如何適用于swift?
可能以類似的方式。Swift項(xiàng)目仍然是Xcode項(xiàng)目,并且支持多個target,但是有提升創(chuàng)建模塊和自定義框架能力的潛在空間。有可能會重新改寫CocoaPods以適應(yīng)這個新特性。有人使用CocoaPods協(xié)助Swift項(xiàng)目工作,并且聰明的CocoaPods開發(fā)人員 。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn