學習 Swift 編程:準備好迎接黃金時段了嗎?
已發表: 2022-03-11Apple 在今年 6 月推出了 Swift,一種用於編寫 iOS 應用程序的新編程語言,在整個 iOS 開發者社區中引起了極大的轟動和興奮。
自發布以來,許多 iOS 開發人員一直在努力解決是否、如何以及何時從 Objective-C 過渡到 Swift 的問題。 對於每個團隊和每個項目,這個問題的答案當然會有所不同。
您可以閱讀大量文章,涵蓋 Swift 的許多優點。 因此,在本文中,我們將重點關注在學習使用 Swift 開發應用程序之前可能需要考慮的一些問題,而不是重複這些相同的觀點。
但首先,讓我們把時鐘撥回去一點……
在 Swift 之前:你會使用 Objective-C,而且你會喜歡它……
那一年是 2010 年,iPhone 還不到 3 年,為 iPhone 編寫原生應用程序的能力才出現了大約 2 年。 當年 4 月 8 日,Apple 發布了 iPhone OS 版本。 iPhone OS(在它更名為 iOS 之前)包括了多任務處理、快速應用程序切換和後台服務等誘人的新功能。 可以理解的是,iPhone 開發人員渴望獲得新的 SDK 並開始使用所有這些令人興奮的新功能。
但 iPhone OS 4 SDK 包含一個意想不到的重磅炸彈。 這個重磅炸彈不在軟件中,而是在使用協議中。 對於 iPhone OS 4 SDK,開發者協議的第 3.3.1 節已更新,包含以下令人不安的語言:
應用程序必須最初是用 Objective-C、C、C++ 編寫的……並且只有用 C、C++ 和 Objective-C 編寫的代碼才能編譯並直接鏈接到文檔化 API。
– iPhone OS 4 SDK 開發者協議第 3.3.1 節
不用說,這個新的限制令許多開發者感到意外。 由史蒂夫喬布斯本人提供的官方更改原因是為了防止使用跨平台工具,例如最近發布的 Flash CS5。 引用喬布斯的話說,“平台和開發人員之間的中間層最終會產生 [原文如此] 不合標準的應用程序”。 但是,Apple 打擊這些“中間層”的方法是限制可用於編寫 iPhone 應用程序的編程語言,這一事實更多地揭示了 Apple 的想法:Objective-C 應該對任何人都足夠好。
同意這一說法是可以原諒的,因為 Objective-C 連續兩年獲得 Tiobe Index 的“年度編程語言”獎。 但現實情況是,Objective-C 的流行是不斷增長的應用生態系統的一個功能,而不是相反。 早在 2010 年,很多人就已經對 Objective-C 不滿意,因此,用其他編程語言編寫 iPhone 應用程序的替代方法已經出現。
最終,在整個開發者社區的壓力下,僅僅五個月後,Apple 就撤銷了對 SDK 開發者協議第 3.3.1 節的這些更改。 不過,信息很明確:如果您想為 iPhone 編寫應用程序,您可能應該使用 Objective-C。
… 或者可能不是。 輸入新的 iOS 語言 Swift。
從那次事件到 2014 年 6 月蘋果公司向開發人員介紹其新語言 Swift 時快進了 4 年。 如果說 4 年前的信息是蘋果對 Objective-C 非常滿意,那麼 Swift 的介紹所傳遞的信息就是蘋果終於準備好承認真相了。 Objective-C 可能不一定是編寫移動應用程序的最佳語言。
關於 Swift 如何是一種比 Objective-C 更“現代”的語言,已經有很多說法了。 如果您對如何學習 Swift 編程語言感興趣,您可能需要查看從 Objective-C 遷移到 Swift 的指南。
不過,您應該注意到的是,Objective-C 和 Swift 語言之間有兩個重要的區別:
- Swift不是C 語言的嚴格超集。
- Swift 是靜態類型的,而不是動態類型的。
不是 C 的嚴格超集意味著 Swift 可以自由地使用原本不允許的語法結構。 例如,這使得在 Swift 中實現自定義運算符成為可能。
靜態類型意味著 Swift 可以利用 Haskell 等語言開創的類型系統的許多最新進展。
儘管在公開之前已經開發了 4 年,但 Swift 仍然是一門年輕的編程語言,因此它有許多警告。
與 Objective-C 的兼容性
iOS 與 OS X 有著共同的遺產,而 OS X 的歷史則源於 1989 年首次發布的 NeXTSTEP 操作系統。NeXTSTEP 最初主要是用 Objective-C 編寫的,OS X 和 iOS 中的許多核心庫都可以追溯到它們的根源回到這些原始實現的方法。 (順便說一句,這就是核心類(如NSString )上無處不在的“NS”前綴的來源。)雖然理論上 Swift 可以在沒有這些核心庫的情況下存在,但現實情況是,您可能在不久的將來編寫任何 Swift 程序必須與Objective-C接口。
值得稱讚的是,Swift 背後的開發人員做得非常出色,使與現有 Objective-C 庫的交互盡可能輕鬆。 這並不是說這個過程完全沒有痛苦。 Apple 提供了一個有用的指南,解釋如何從 Swift 調用 Objective-C 代碼,反之亦然,但有一些重要的阻抗不匹配需要注意。
也許最明顯的不匹配與頭文件有關。 Objective-C,由於它的 C 根源,仍然要求函數在被調用之前被聲明。 調用庫時,這些聲明將在庫的頭文件中找到。 然而,Swift 不使用頭文件。 所以,如果你想從 Objective-C 調用 Swift 代碼,你首先需要創建一個“橋接頭”。 雖然從概念上看這似乎並不復雜,但在實踐中,它實際上可能是一項艱鉅的任務。
Swift 和 Objective-C 之間接口的另一組複雜性源於它們類型系統的固有差異。 Swift 從其他現代語言中汲取靈感,廢除了nil的概念。 取而代之的是 Swift 的可選類型。 例如,僅當文件已存在時才打開文件的方法的返回類型為File? (而不僅僅是File )在 Swift 中。 通過跟踪類型可選的所有地方,Swift 編譯器可以有效地避免遇到可怕的“空指針錯誤”。 當然,除非你調用的是 Objective-C。 由於 Objective-C 對不返回nil沒有做出這樣的保證,Swift 有一個特殊的類型,稱為Implicitly Unwrapped Optionals ,在調用 Objective-C 代碼時使用。 這些類型可以被視為 Swift 語言中的可選項,以及存在檢查所需的所有伴隨開銷。 或者,它們可以與任何非可選類型一樣使用,但是如果 Objective-C確實返回nil ,您最終會出現運行時錯誤,因此您會失去一些 Swift 的編譯時安全保證。

最後,在 Swift 和 Objective-C 之間進行編程時需要考慮的稍微微妙的不匹配與這兩種語言中對象和類的創建方式有關。 Objective-C,由於其動態特性,利用動態調度來調用對像上的方法(通過objc_msgSend )。 Swift 當然可以使用動態調度,但由於它是靜態類型的,它還可以選擇使用vtable來存儲每個方法的函數指針。 Swift 使用這兩種機制中的哪一種取決於幾個因素。 平面舊 Swift 對象將使用vtable機制,除非類中的類或方法使用@objc Swift 屬性進行註釋。 從 Objective-C 類繼承的 Swift 類將對繼承的方法使用動態調度,但不會對子類引入的任何新方法使用動態調度(不過,您可以再次通過@objc屬性強制使用動態調度)。 無論如何,Swift 代碼將始終能夠使用 Swift 類,但 Objective-C 代碼只能使用已正確註釋的 Swift 對象和方法。
比 Objective-C 更快?
當 Apple 推出其產品時,特別強調 Swift 的好處之一就是它的速度。 當您考慮到 Apple 不願從 Objective-C 切換到更高級語言的一個原因時,這是可以理解的,因為 Objective-C 本質上是 C 的擴展,能夠創建更快、更高效的程序而不是像 Python 或 Ruby 這樣的東西。 即便如此,就絕對性能而言,Objective-C 也不是火箭飛船,這在很大程度上要歸功於動態類型。 因此,隨著 Swift 採用靜態類型系統,人們會期望 Swift 至少應該與 Objective-C 一樣快,或者更快。
當然,俗話說,“謊言分三種:謊言、該死的謊言、基準。” (或類似的東西……)當然,Swift 語言可能運行得更快的原因有很多。 不幸的是,似乎 Swift 使用 Apple 的 ARC(自動引用計數)技術進行內存管理的方式有時會導致 Swift 的編譯器生成的程序明顯變慢,尤其是在優化設置較低的情況下(例如您可能在開發過程中使用的程序)。 好消息是,對 Swift 的改進似乎在不斷解決這個問題,因此在不久的將來,Swift 生成可執行文件的速度可能至少與 Objective-C 一樣快或更快。
不過,Swift 的速度還有另一個警告。 Swift 的全部意義在於,開發人員不會編寫與他們在 Objective-C 中編寫的代碼相同的代碼。 這對性能意味著什麼? 嗯,這當然意味著比較 Swift 和 Objective-C 之間的性能比簡單的基準測試所能揭示的要復雜得多。 這也意味著比較生成的可執行文件的絕對運行時性能只能說明一半。
每個人都想要快速的程序,但開發速度通常同樣重要——如果不是更重要的話。 一種更具表現力的語言,能夠以更少的代碼行完成更多的工作,在這方面可能是一個巨大的好處。 另一方面,在編輯-編譯-運行-調試週期佔據程序員大部分時間的編譯語言中工作時,慢速編譯器確實會損害生產力。 雖然證據主要是軼事,但似乎 Swift 編譯器目前的速度慢到令人討厭,尤其是在處理使用 Swift 高級類型系統的代碼時。 一個小組甚至發現編譯速度的問題足以促使他們切換回 Objective-C。
編譯器
說到 Swift 編譯器,在考慮切換到新的 Swift 語言時,它本身就是更多警告的來源。 除了編譯速度之外,隨著 Swift 從 Apple 的一小部分開發人員中脫穎而出並被大眾所釋放,編譯器在壓力下開始出現裂縫。 甚至還有一個完整的 GitHub 存儲庫專門用於收集會導致 Swift 編譯器崩潰的代碼示例。
還有一個問題是 Swift 編譯器將如何改變。 GitHub 上的另一個項目正在收集社區關於 Swift 可能會發生哪些變化的猜測和分析。 例如,自定義運算符會給解析器帶來很大的壓力。 最初,Swift 中的自定義運算符不能使用問號 (?) 字符。 雖然這一問題已在最新的 Swift 版本中得到修復,但不斷增長的 Swift 開發者社區不斷湧入請求,以便在可以被視為有效的自定義運算符方面獲得更大的靈活性。
每當您聽到一種語言的解析器在不斷變化時,它都應該讓您停下來。 語言的解析器是編程語言的核心和靈魂。 在可以應用任何語言語義來賦予代碼含義之前,解析器首先確定什麼是有效代碼,什麼是無效代碼。 因此,令人鼓舞的是,Apple 已承諾確保 Swift 具有一定程度的運行時兼容性。 但是,這並不一定保證 Swift 代碼無需為每個新版本的 Xcode 和/或 iOS 重新編譯即可運行。 它也不保證您不需要重寫部分 Swift 代碼來保持與 Swift 未來版本的兼容性。 但同樣,Apple 承諾讓這個過程盡可能輕鬆,這至少是一些小小的安慰。
社區
一些有史以來最糟糕的編程語言(將保持無名)一直受到鼓舞,早在常識認為它們應該僅靠各自社區的力量就應該被歸入失敗技術的垃圾箱之後很久。 同時,由於缺乏一個社區而未能佔據一席之地的真正優秀的編程語言的集合數不勝數。 強大的社區製作教程,在 Stack Overflow 上回答問題,在線或親自參加會議分享故事、提示和技巧,並相互編寫和共享有用的庫。 在選擇用於項目的語言時,社區絕對是需要考慮的因素。
遺憾的是,iOS/Objective-C 社區在友好和熱情方面並沒有最好的聲譽。 這種情況正在逐漸發生變化,開源在 Objective-C 開發中扮演著越來越重要的角色。 儘管如此,在這個早期階段,很難說 Swift 社區未來會是什麼樣子。 它是否主要由孤立的開發人員組成,只使用官方的 Apple API 和他們自己的私人代碼集合? 或者它會是一個充滿活力的團體社區,分享技巧、竅門和有用的圖書館?
社區角色的另一個方面是 Swift 開發人員本身的角色。 編程的總體趨勢是從專有編程語言和平台轉向開源解決方案。 開源開發,尤其是在編程語言和運行時級別,可能是一個真正的優勢。 雖然 Swift 開發人員多次表示他們的意圖是完全開源 Swift 語言和運行時,但這種情況尚未發生,因此需要謹慎。
也就是說,Swift 背後的開發人員與長期運行的 LLVM 項目背後的一些開發人員相同。 LLVM 並不是一個完美的類比,因為它是作為伊利諾伊大學厄巴納-香檳分校的一個項目在開放中開始的。 但值得稱讚的是,核心開發人員仍然非常開放並與社區互動,即使他們中的大多數人已經過渡到為 Apple 工作。 可以完全合理地期望 Swift 語言將繼續(大部分)以開放的方式開發,儘管來自社區的補丁和功能建議是否會進入該語言還有待觀察。
我應該學習 Swift 嗎?
當然,這裡沒有“一刀切”的答案。 與往常一樣,為工作選擇正確的工具需要對相關項目的所有細節有深入的了解。 當然,此時此刻,Objective-C 仍然是 iOS 開發的“安全”選擇,但 Swift 絕對值得考慮。
然而,Swift 給 iOS 開髮帶來的最重要的變化是,許多開發人員將第一次問自己一個問題:“我應該使用什麼語言?” 鑑於 Apple、Objective-C 和 iOS 平台的歷史,僅此一項更改就相當令人興奮,尤其是考慮到選擇不是二元的。 雖然 Apple 已經明確表達了他們的偏好,但整個 iOS 開發者社區多年來一直在努力工作,已經為這個問題提供了更多可能的答案。
