Swift思量與初探:我須要學習Swift嗎?

最近,除了N多的基於Swift的服務端開發框架,筆者不禁深思,到底該這麼評價Swift呢?不能否認,在iOS的開發領域,Swift是比OJC擁有着優點,那麼在通用語言這個層次上比較時,它又如何呢?html

Introduction

Apple 在推出 Swift 時就將其冠以先進,安全和高效的新一代編程語言之名。前兩點在 Swift 的語法和語言特性中已經表現得淋漓盡致:像是尾隨閉包,枚舉關聯值,可選值和強制的類型安全等都是 Swift 顯而易見的優勢。git

Comparison

近來Swift與Rust都挺好的,一個背靠Apple,一個是Mozilla的親兒子。不能否認這兩者都是工程領域的集大成者,不過筆者認爲Swift是會比D或者Rust具備更大的可用性與吸引力,固然,他們的瞄準的目標點也不同。D與Rust適合於那些長期使用C++而且已經適應了要去掌握N多的語法與概念的,可是想要使用些更加清晰明瞭與安全的語言。這類型的開發者每每從事着相似於遊戲引擎、編譯器、加解密庫、HTML渲染引擎等等相似的工做。github

Swift呢,更多意義上是一門面向於應用編程的語言,它很容易上手,在某些方面它應該與Go、Java、Python以及C#相提並論。不過Swift比這些會更容易開始學習,它的helloworld只須要一行代碼就行了,而且它是支持函數的(不像Java那樣徹底的OO)。你不須要學習任何的類與對象的知識就能夠開始撰寫簡易的Swift的代碼。基於此,Swift是更合適用做一種教學語言的,它還有像腳本語言同樣的交互環境,也就是REPL以及Xcode自己提供的PlayGround。objective-c

綜上所述,Swift擁有着被普遍使用以及當作第一學習語言的潛質。而且,Swift並非像PHP那樣的語法特性較少的語言,它擁有足夠的深度來知足Rust或者D這樣的用戶的需求。與Go相比的話,Go背靠Google,也是個很是容易上手的語言,而且號稱自帶併發。Swift在語法層次上會更加高級,而且Swift並無使用GC機制,所以能夠與C更好地相兼容。也就是說,你能夠用Swift編寫任何的庫來供任何語言使用,只要這些語言可使用C的庫。這些特質保證了Swift擁有着比Java、C#、Python、Ruby以及Go更廣闊的適用範圍。後面這幾個傢伙,由於有GC的存在,不適合爲其餘語言提供基本庫。我也很喜歡Go,可是毫無疑問,Swift會是個更加嚴謹與安全的語言。類型檢測系統會幫助處理不少的錯誤,Go目前是很合適於Web開發可是不適合科學計算與遊戲引擎這些你必需要大量自定義操做符來處理向量啊、矩陣運算這樣的。編程

所以,Swift能夠被定義爲一個安全而且用戶友好的語言,而且能夠像腳本語言那樣方便實驗與使用。swift

Performance

Swift 具備一門高效語言所須要具有的絕大部分特色。與 Ruby 或者 Python 這樣的解釋型語言不須要再作什麼對比了,相較於其前輩的 Objective-C,Swift 在編譯期間就完成了方法的綁定,所以方法調用上再也不是相似於 Smalltalk 的消息發送,而是直接獲取方法地址並進行調用。雖然 Objective-C 對運行時查找方法的過程進行了緩存和大量的優化,可是不能否認 Swift 的調用方式會更加迅速和高效。緩存

另外,與 Objective-C 不一樣,Swift 是一門強類型的語言,這意味 Swift 的運行時和代碼編譯期間的類型是一致的,這樣編譯器能夠獲得足夠的信息來在生成中間碼和機器碼時進行優化。雖然都使用 LLVM 工具鏈進行編譯,可是 Swift 的編譯過程相比於 Objective-C 要多一個環節 -- 生成 Swift 中間代碼 (Swift Intermediate Language,SIL)。SIL 中包含有不少根據類型假定的轉換,這爲以後進一步在更低層級優化提供了良好的基礎,分析 SIL 也是咱們探索 Swift 性能的有效方法。安全

最後,Swift 具備良好的內存使用的策略和結構。Swift 標準庫中絕大部分類型都是 struct,對值類型的 使用範圍之廣,在近期的編程語言中可謂數一數二。本來值類型不可變性的特色,每每致使對於值的使用和修改意味着建立新的對象,可是 Swift 巧妙地規避了沒必要要的值類型複製,而僅只在必要時進行內存分配。這使得 Swift 在享受不可變性帶來的便利以及避免沒必要要的共享狀態的同時,還可以保持性能上的優秀。閉包

編譯器優化

Swift 編譯器十分智能,它能在編譯期間幫助咱們移除不須要的代碼,或者將某些方法進行內聯 (inline) 處理。編譯器優化的強度能夠在編譯時經過參數進行控制,Xcode 工程默認狀況下有 Debug 和 Release 兩種編譯配置,在 Debug 模式下,LLVM Code Generation 和 Swift Code Generation 都不開啓優化,這能保證編譯速度。而在 Release 模式下,LLVM 默認使用 "Fastest, Smallest [-Os]",Swift Compiler 默認使用 "Fast [-O]",做爲優化級別。咱們另外還有幾個額外的優化級別能夠選擇,優化級別越高,編譯器對於源碼的改動幅度和開啓的優化力度也就越大,同時編譯期間消 耗的時間也就越多。雖然絕大部分狀況下沒有問題,可是仍然須要小心的是,一些優化等級採用的是激進的優化策略,而禁用了一些檢查。這可能在源碼很複雜的情 況下致使潛在的錯誤。若是你使用了很高的優化級別,請再三測試 Release 和 Debug 條件下程序運行的邏輯,以防止編譯器優化所帶來的問題。併發

值得一提的是,Swift 編譯器有一個頗有用的優化等級:"Fast, Whole Module Optimization",也即 -O -whole-module-optimization。在這個優化等級下,Swift 編譯器將會同時考慮整個 module 中全部源碼的狀況,並將那些沒有被繼承和重載的類型和方法標記爲 final,這將盡量地避免動態派發的調用,或者甚至將方法進行內聯處理以加速運行。開啓這個額外的優化將會大幅增長編譯時間,因此應該只在應用要發佈的時候打開這個選項。

雖然如今編譯器在進行優化的時候已經足夠智能了,可是在面對編寫得很是複雜的狀況時,不少本應實施的優化可能失效。所以保持代碼的整潔、乾淨和簡單,可讓編譯器優化良好工做,以獲得高效的機器碼。

註釋與換行

註釋

請將你的代碼中的非執行文本註釋成提示或者筆記以方便你未來閱讀。Swift 的編譯器將會在編譯代碼時自動忽略掉註釋部分。

Swift 中的註釋與C 語言的註釋很是類似。單行註釋以雙正斜槓做(//)爲起始標記:

// 這是一個註釋

你也能夠進行多行註釋,其起始標記爲單個正斜槓後跟隨一個星號(/),終止標記爲一個星號後跟隨單個正斜槓(/):

/* 這是一個, 多行註釋 */

與C 語言多行註釋不一樣,Swift 的多行註釋能夠嵌套在其它的多行註釋之中。你能夠先生成一個多行註釋塊,而後在這個註釋塊之中再嵌套成第二個多行註釋。終止註釋時先插入第二個註釋塊的終止標記,而後再插入第一個註釋塊的終止標記:

/* 這是第一個多行註釋的開頭 /* 這是第二個被嵌套的多行註釋 */ 這是第一個多行註釋的結尾 */

經過運用嵌套多行註釋,你能夠快速方便的註釋掉一大段代碼,即便這段代碼之中已經含有了多行註釋塊。

Objective-C混合編程

參考資料

  • 從Objective-C到Swift

  • swift與objective-c混編

  • Swift and Objective-C in the Same Project

Swift 與 Objective-C混合調用示意圖

Swift類引用Objective-C文件

由於Swift沒有內嵌的頭文件機制,所以Swift調用Objective-C須要一個名爲「<工程名>-Bridging-Header.h」的橋接頭文件。橋接頭文件的做用是爲Swift調用Objective-C對象搭建一個橋,它的命名必須是「<工程名>- Bridging-Header.h」,咱們須要在橋接頭文件中引入Objective-C頭文件,全部的Swift類會自動引用這個頭文件。

橋接文件

橋接文件設置

  • OJC類以下:

//
//  ObjcFunc.h
//

# import <Foundation/Foundation.h>

@interface ObjcFunc : NSObject

-(NSString*)sayHello:(NSString*)greeting withName: (NSString*)name;

@end

//
//  ObjcFunc.m
//

# import "ObjcFunc.h"

# import "CombinedProgram-Swift.h"

@implementation ObjcFunc

- (NSString*)sayHello:(NSString*)greeting withName: (NSString*)name{

    NSString *string = [NSString stringWithFormat:@"Hi,%@ %@.",name,greeting];

    return string;

  }

@end
  • Swift類中調用

import Foundation
@objc class SwiftFunc: NSObject {
  func sayHello() -> Void {
  var obj : ObjcFunc = ObjcFunc()
  println(obj.sayHello("Hello", withName: "Swift"));
  return
  }
}

Objective-C類引用Swift文件

(1)在Building Settings -> Packaging -> Defining中選定Module Name;

(2)在OJC的頭文件中引入:#import "{ModuleName}-swift.h"

SwiftFunc* obj = [[SwiftFunc alloc] init];
[obj sayHello];

有時候會發現Xcode沒法自動生成*-Swift.h文件,能夠參考StackOverflow上的這篇文章。該文章總結下來,咱們須要進行如下兩大步檢測:

(1)檢測你的Xcode的配置

Product Module Name : myproject

Defines Module : YES

Embedded Content Contains Swift : YES

Install Objective-C Compatibility Header : YES

sObjective-C Bridging Header : $(SRCROOT)/Sources/SwiftBridging.h

(2)檢查你的Swift類是否正規

要保證你的Swfit類中已經使用@objc關鍵字聲明瞭一個繼承自NSObject的類。Xcode不會爲存在任何編譯錯誤的類進行編譯操做。

(3)忽略Xcode的報錯,先編譯一下

語法要點

! VS ?

在Swift中常常看到!與?兩個操做符,譬如在類型轉換、可選類型構造中都用到,用Apple官方的話說:

It may be easiest to remember the pattern for these operators in Swift as: ! implies 「this might trap,」 while ?indicates 「this might be nil.」

就是!操做符表示我無論你編譯器,我確定要這麼作,那麼有可能致使運行時崩潰。而?操做符表示這個多是nil,你幫我查查有沒有進行完備的空檢查。

Reference

Tutorial & Docs

  • 中文版 Apple 官方 Swift 教程《The Swift Programming Language》

  • Swift學習筆記

Forum & Lessons

Blog & News

Book & Resources

相關文章
相關標籤/搜索