Swift學習: 從Objective-C到Swift

文章組織脈絡:java

  • 從Objective-C到Swift的語法差別。咱們熟悉的Objective-C特性在Swift中如何展示。react

  • 從Objective-C到Swift的進步改進。研究對比Swift在安全性,易用性上的提高,給咱們帶來的新編程範式。ios

目錄:git

1.屬性(property)和實例變量(instance variable)github

2.控制流web

3.函數編程

4.類與初始化(Initializers)swift

5.枚舉與結構體數組

6.協議(Protocols)安全

7.Swift與Cocoa

8.總結

1.屬性(property)和實例變量(instance variable)

Objective-C property in Swift world

在Cocoa世界開發的過程當中,咱們最常打交道的是property.

典型的聲明爲:

1
@property (strong,nonatomic) NSString *string;

而在Swift當中,擺脫了C的包袱後,變得更爲精煉,咱們只需直接在類中聲明便可

1
2
3
class Shape {
     var  name =  "shape"
}

注意到這裏,咱們再也不須要@property指令,而在Objective-C中,咱們能夠指定property的attribute,例如strong,weak,readonly等。

而在Swift的世界中,咱們經過其餘方式來聲明這些property的性質。

須要注意的幾點:

  • strong: 在Swift中是默認的

  • weak: 經過weak關鍵詞申明

1
weak  var  delegate: UITextFieldDelegate?
  • readonly,readwrie 直接經過聲明常量let,聲明變量var的方式來指明

  • copy 經過@NSCopying指令聲明。

值得注意的是String,Array和Dictionary在Swift是以值類型(value type)而不是引用類型(reference type)出現,所以它們在賦值,初始化,參數傳遞中都是以拷貝的方式進行(簡單來講,String,Array,Dictionary在Swift中是經過struct實現的)

延伸閱讀:Value and Reference Types

  • nonatomic,atomic 全部的Swift properties 都是nonatomic。可是咱們在線程安全上已經有許多機制,例如NSLock,GCD相關API等。我的推測緣由是蘋果想把這一個原本就用的不多的特性去掉,線程安全方面交給平時咱們用的更多的機制去處理。

而後值得注意的是,在Objective-C中,咱們能夠跨過property直接與instance variable打交道,而在Swift是不能夠的。

例如:咱們能夠不須要將someString聲明爲property,直接使用便可。即便咱們將otherString聲明爲property,咱們也能夠直接用_otherString來使用property背後的實例變量。

1
2
3
4
@interface SomeClass : NSObject {
   NSString *someString;
}
@property(nonatomic, copy) NSString* otherString;

而在Swift中,咱們不能直接與instance variable打交道。也就是咱們聲明的方式簡化爲簡單的一種,簡單來講在Swift中,咱們只與property打交道。

A Swift property does not have a corresponding instance variable, and the backing store for a property is not accessed directly

小結

  • 所以以前使用OC致使的像巧哥指出的開發爭議就再也不須要爭執了,在Swift的世界裏,咱們只與property打交道。

  • 而且咱們在OC中init和dealloc不能使用屬性self.property = XXX來進行設置的狀況得以解決和統一。

(不知道這一條規定,在init直接用self.property = value 的同窗請自覺閱讀iOS夯實:內存管理)

我的以爲這看似小小一點變更使Swift開發變得更加安全以及在代碼的風格更爲統一與穩定。

Swift property延伸:

  • Stored Properties和Computed properties

在Swift中,property被分爲兩類:Stored Properties和Computed properties 簡單來講,就是stored properties 可以保存值,而computed properties只提供getter與setter,利用stored properties來生成本身的值。我的感受Computed properties更像方法,而不是傳統意義的屬性。可是這樣一個特性存在,使得咱們更容易組織咱們的代碼。

延伸閱讀:computed property vs function

  • Type Properties

Swift提供了語言級別定義類變量的方法。

In C and Objective-C, you define static constants and variables associated with a type as global static variables.In Swift, however, type properties are written as part of the type’s definition, within the type’s outer curly braces, and each type property is explicitly scoped to the type it supports.

在Objective-C中,咱們只能經過單例,或者static變量加類方法來本身構造類變量:

1
2
3
4
5
6
7
8
9
10
11
12
@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end
 
@implementation Model
static int value;
+ (int) value
{ @synchronized(self) {  return  value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Foo.h
@interface Foo {
}
 
+(NSDictionary*) dictionary;
 
// Foo.m
+(NSDictionary*) dictionary
{
   static NSDictionary* fooDict = nil;
   
   static dispatch_once_t oncePredicate;
   
   dispatch_once(&oncePredicate, ^{
         // create dict
     });
     
   return  fooDict;
}

而在Swift中咱們經過清晰的語法便能定義類變量:

經過static定義的類變量沒法在子類重寫,經過class定義的類變量則可在子類重寫。

1
2
3
4
5
6
7
8
9
struct SomeStructure {
     static  var  storedTypeProperty =  "Some value."
     static  var  computedTypeProperty: Int {
         return  1
     }
     class  var  overrideableComputedTypeProperty: Int {
         return  107
     }
}

同時利用類變量咱們也有了更優雅的單例模式實現:

1
2
3
4
class singletonClass {
     static let sharedInstance = singletonClass()
     private init() {}  // 這就阻止其餘對象使用這個類的默認的'()'初始化方法
}

Swift單例模式探索:The Right Way to Write a Singleton

  • 延伸:目前Swift支持的type propertis中的Stored Properties類型不是傳統意義上的類變量(class variable),暫時不能經過class 關鍵詞定義,經過static定義的類變量相似java中的類變量,是沒法被繼承的,父類與子類的類變量指向的都是同一個靜態變量。

延伸閱讀: Class variables not yet supported

1
2
3
4
5
6
class SomeStructure {
     class  var  storedTypeProperty =  "Some value."
}
 
//Swift 2.0 
Error: Class stored properties not yet supported  in  classes

經過編譯器拋出的錯誤信息,相信在將來的版本中會完善Type properties。

2.控制流

Swift與Objective-C在控制流的語法上關鍵詞基本是一致的,可是擴展性和安全性獲得了很大的提高。

主要有三種類型的語句

  • if,switch和新增的guard

  • for,while

  • break,continue

主要差別有:

關於if

語句裏的條件再也不須要使用()包裹了。

1
2
3
4
let number = 23
if  number < 10 {
     print( "The number is small" )
}

可是後面判斷執行的的代碼必須使用{}包裹住。

爲何呢,在C,C++等語言中,若是後面執行的語句只有語句,咱們能夠寫成:

1
2
3
   int number = 23
     if  (number < 10)
         NSLog( "The number is small" )

可是若是有時要在後面添加新的語句,忘記添加{},災難就極可能發送。

:) 像蘋果公司本身就犯過這樣的錯誤。下面這段代碼就是著名的goto fail錯誤,致使了嚴重的安全性問題。

1
2
3
4
5
6
7
   if  ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
     goto fail;
     goto fail;   // :)注意 這不是Python的縮減
   ... other checks ...
   fail:
     ... buffer frees (cleanups) ...
     return  err;

最終在Swift,蘋果終於在根源上消除了可能致使這種錯誤的可能性。

if 後面的條件必須爲Boolean表達式

也就是不會隱式地與0進行比較,下面這種寫法是錯誤的,由於number並非一個boolean表達式,number != 0纔是。

1
2
3
int number = 0
if  number{
}

關於for

for循環在Swift中變得更方便,更強大。

得益於Swift新添加的範圍操做符...與...<

咱們可以將以前繁瑣的for循環:

1
2
3
4
for  (int i = 1; i <= 5; i++)
{
     NSLog(@ "%d" , i);
}

改寫爲:

1
2
3
for  index  in  1...5 {
     print(index)
}

固然,熟悉Python的親們知道Python的range函數很方便,咱們還能自由選擇步長。 像這樣:

>>> range(1,5) #表明從1到5(不包含5)

[1, 2, 3, 4]

>>> range(1,5,2) #表明從1到5,間隔2(不包含5)

[1, 3]

雖然在《The Swift Programming Language》裏面沒有提到相似的用法,可是在Swift中咱們也有優雅的方法辦到。

1
2
3
for  index  in  stride(from: 1, through: 5, by: 2) {
     print(index)
} // through是包括5

而後對字典的遍歷也加強了.在Objective-c的快速枚舉中咱們只能對字典的鍵進行枚舉。

1
2
3
4
NSString *key;
for  (key  in  someDictionary){
      NSLog(@ "Key: %@, Value %@" , key, [someDictionary objectForKey: key]);
}

而在Swift中,經過tuple咱們能夠同時枚舉key與value:

1
2
3
4
let dictionary = [ "firstName" : "Mango" , "lastName" : "Fang" ]
for  (key,value)  in  dictionary{
     print(key+ " " +value)
}

關於Switch

Swich在Swift中也獲得了功能的加強與安全性的提升。

不須要Break來終止往下一個Case執行

也就是下面這兩種寫法是等價的。

1
2
3
4
5
6
7
8
9
let character =  "a"
switch  character{
     case  "a" :
         print( "A" )
     break
     case  "b" :
         print( "B" )
     break
default : print( "character" )
1
2
3
4
5
6
7
let character =  "a"
switch  character{
     case  "a" :
         print( "A" )
     case  "b" :
         print( "B" )
default : print( "character" )

這種改進避免了忘記寫break形成的錯誤,本身深有體會,曾經就是由於漏寫了break而花了一段時間去debug。

若是咱們想不一樣值統一處理,使用逗號將值隔開便可。

1
2
3
4
switch  some value to consider {
case  value 1,value 2:
     statements
}

Switch支持的類型

在OC中,Swtich只支持int類型,char類型做爲匹配。

而在Swift中,Switch支持的類型大大的拓寬了。實際上,蘋果是這麼說的。

A switch statement supports any kind of data

這意味在開發中咱們可以可以對字符串,浮點數等進行匹配了。

以前在OC繁瑣的寫法就能夠進行改進了:

1
2
3
4
5
6
7
8
9
if  ([cardName isEqualToString:@ "Six" ]) {
     [self setValue:6];
else  if  ([cardName isEqualToString:@ "Seven" ]) {
     [self setValue:7];
else  if  ([cardName isEqualToString:@ "Eight" ]) {
     [self setValue:8];
else  if  ([cardName isEqualToString:@ "Nine" ]) {
     [self setValue:9];
}
1
2
3
4
5
6
7
8
9
10
switch  carName{
     case  "Six" :
         self.vaule = 6
     case  "Seven" :
         self.vaule = 7
     case  "Eight" :
         self.vaule = 8
     case  "Night" :
         self.vaule = 9   
}

3.函數

對於在OC中,方法有兩種類型,類方法與實例方法。方法的組成由方法名,參數,返回值組成。

在Swift中函數的定義基本與OC同樣。

主要區別爲:

  1. 經過func關鍵詞定義函數

  2. 返回值在->關鍵詞後標註

各舉一個類方法與實例方法例子。

1
2
+ (UIColor*)blackColor
- (void)addSubview:(UIView *)view

對應的swift版本

1
2
     class func blackColor() -> UIColor  //類方法, 經過 class func 關鍵詞聲明
     func addSubview(view: UIView)  //實例方法

改進:

在Swift中,函數的最重要的改進就是函數做爲一等公民(first-class),和對象同樣能夠做爲參數進行傳遞,能夠做爲返回值,函數式編程也成爲了Swift支持的編程範式。

In computer science, a programming language is said to have first-class functions if it treats functions as first-class citizens. Specifically, this means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures

讓咱們初略感覺一下函數式編程的魅力:

舉一個例子,咱們要篩選出一個數組裏大於4的數字。

在OC中咱們可能會用快速枚舉來進行篩選。

1
2
3
4
5
6
7
    NSArray *oldArray = @[@1,@2,@3,@4,@5,@6,@7,@8,@9,@10];
     NSMutableArray *newArray;
     for  (NSNumber* number  in  oldArray) {
         if  ([number compare:@4] == NSOrderedDescending ) {
             [newArray addObject:number];
         }
     }

而在Swift中,咱們用兩行代碼解決這個問題:

1
2
let oldArray = [1,2,3,4,5,6,7,8,9,10]
let newArray = oldArray.filter({$0 > 4})

進一步瞭解Swift的函數式編程能夠經過這篇優秀的博客Functional Reactive Programming in Swift

  • 我的以爲另一個很棒的改進是:Default parameter values

在咱們的項目中,常常會不斷進行功能的增添。爲了新增特性,許多方法在開發的過程當中不斷變更。舉一個例子:咱們開始有一個tableViewCell,它的設置方法一開始簡單地須要一個Model參數:

1
func configureCellWithModel(Model: model)

不久以後,咱們想對部分Cell增添一個設置背景顏色的功能。方法須要再接收多一個參數:

1
func configureCellWithModel(Model: model,color:UIColor)

這個時候方法改變,因此涉及到這些方法的地方都須要修改。給咱們形成的困擾

一是:須要作許多重複修改的工做。

二是:沒法作得很好的擴展和定製,有些地方的cell須要設置顏色,有些不須要。可是在OC裏,咱們只能對全部的cell都賦值。你可能以爲咱們能夠寫兩個方法,一個接收顏色參數,一個不接受。可是咱們知道這不是一個很好的解決方法,會形成冗餘的代碼,維護起來也不方便。

而在Swift中,default parameter values的引入讓咱們可以這樣修改咱們的代碼:

1
func configureCellWithModel(Model: model,color:UIColor = UIColor.whiteColor())

這樣的改進能讓咱們寫出的代碼更具向後兼容性,減小了咱們的重複工做量,減小了犯錯誤的可能性。

4.類與初始化(Initializers)

文件結構與訪問控制

在swift中,一個類再也不分爲interface(.h)與implementation(.m)兩個文件實現,直接在一個.swift文件裏進行處理。好處就是咱們只需管理一份文件,以往兩頭奔波修改的狀況就獲得解放了,也減小了頭文件與實現文件不一樣步致使的錯誤。

這時咱們會想到,那麼咱們如何來定義私有方法與屬性呢,在OC中咱們經過在class extension中定義私有屬性,在.m文件定義私有方法。

而在Swift中,咱們經過Access Control來進行控制。

properties, types, functions等可以進行版本控制的統稱爲實體。

  • Public:能夠訪問本身模塊或應用中源文件裏的任何實體,別人也能夠訪問引入該模塊中源文件裏的全部實體。一般狀況下,某個接口或Framework是能夠被任何人使用時,你能夠將其設置爲public級別。

  • Internal:能夠訪問本身模塊或應用中源文件裏的任何實體,可是別人不能訪問該模塊中源文件裏的實體。一般狀況下,某個接口或Framework做爲內部結構使用時,你能夠將其設置爲internal級別。

  • Private:只能在當前源文件中使用的實體,稱爲私有實體。使用private級別,能夠用做隱藏某些功能的實現細節

一個小技巧,若是咱們有一系列的私有方法,咱們能夠把它們組織起來,放進一個extension裏,這樣就不須要每一個方法都標記private,同時也便於管理組織代碼:

1
2
3
4
5
// MARK: Private
private extension ViewController {
     func privateFunction() {
     }
}

建立對象與alloc和init

關於初始化,在Swift中建立一個對象的語法很簡潔:只需在類名後加一對圓括號便可。

1
var  shape = Shape()

而在Swift中,initializer也與OC有所區別,Swift的初始化方法不返回數據。而在OC中咱們一般返回一個self指針。

Unlike Objective-C initializers, Swift initializers do not return a value. Their primary role is to ensure that new instances of a type are correctly initialized before they are used for the first time.

Swift的初始化方法讓咱們只關注對象的初始化。以前在OC世界中爲何要self = [super init]?。這種問題得以免。Swift幫助咱們處理了alloc的過程。也讓咱們的代碼更簡潔明確。

而在Swift中,init也有了更嚴格的規則。

  • 對於全部Stored Properties,都必須在對象被建立出來前設置好。也就是咱們必須在init方法中賦好值,或是直接給屬性提供一個默認值。

若是有property能夠被容許在初始出來時沒有值,也就是須要在建立出來後再賦值,或是在程序運行過程均可能不會被賦值。那麼這個property必須被聲明爲optional類型。該類型的屬性會在init的時候初始化爲nil.

  • initializer嚴格分爲Designated Initializer和Convenience Initializer 而且有語法定義。

而在Objective-C中沒有明確語法標記哪一個初始化方式是convenience方法。關於Designated Initializer可參閱以前的:Objective-C 拾遺:designated initializer

1
2
3
4
5
6
7
init(parameters) {
     statements
}
 
convenience init(parameters) {
     statements
}

5.枚舉與結構體

  • 枚舉

在Swift中,枚舉是一等公民。(first-class)。可以擁有方法,computed properties等以往只有類支持的特性。

在C中,枚舉爲每一個成員指定一個整型值。而在Swift中,枚舉更強大和靈活。咱們沒必要給枚舉成員提供一個值。若是咱們想要爲枚舉成員提供一個值(raw value),咱們能夠用字符串,字符,整型或浮點數類型。

1
2
3
4
5
6
7
enum CompassPoint {
case  North
case  South
case  East
case  West
   }
   var  directionToHead = CompassPoint.West
  • 結構體

Struct在Swift中和類有許多相同的地方,能夠定義屬性,方法,初始化方法,可經過extension擴展等。

不一樣的地方在於struct是值類型.在傳遞的過程當中都是經過拷貝進行。

在這裏要提到在前面第一節處提到了String,Array和Dictionary在Swift是以值類型出現的。這背後的緣由就是String,Array,Dictionary在Swift中是經過Struct實現的。而以前在Objective-C它們都是經過class實現的。

Swift中強大的Struct使得咱們可以更多與值類型打交道。Swift的值類型加強了不可變性(Immutabiliity)。而不可變性提高了咱們代碼的穩定性,多線程併發的安全性。

在WWDC2014《Advanced iOS Application Architecture and Patterns》中就有一節的標題是Simplify with immutability。

延伸閱讀:WWDC心得:Advanced iOS Application Architecture and Patterns

6.協議(Protocols)

語法:

在Objective-C中咱們這麼聲明Protocol:

1
2
3
@protocol SampleProtocol
- (void)someMethod;
@end

而在Swift中:

1
2
3
4
protocol SampleProtocol 
{
     func someMethod()
}

在Swift遵循協議:

1
2
3
4
class AnotherClass: SomeSuperClass, SampleProtocol
{
     func someMethod() {}
}

那麼以前Objective-C的protocol中,咱們能夠標誌optional。那在Swift中呢?

遺憾的是,目前純Swift的protocol還不支持optional。但根據蘋果官方論壇的一位員工的回答,將來Swift是會支持的。

Optional methods in protocols are limited to @objc protocols only because we haven't implemented them in native protocols yet. This is something we plan to support. We've gotten a number of requests for abstract/pure virtual classes and methods too.

— Joe Groff

Source: https://devforums.apple.com/message/1051431#1051431

protocol和delegate是緊密聯繫的。那麼咱們在Swift中如何定義Delegate呢?

1
2
3
4
5
protocol MyDelegate : class {
}
class MyClass {
     weak  var  delegate : MyDelegate?
}

注意到上面的protocol定義後面跟着的class。這意味着該protocol只能被class類型所遵照。

而且只有遵照了class protocol的delegate才能定義爲weak。這是由於在Swift中,除了class可以遵照協議,枚舉和結構一樣可以遵照協議。而枚舉和結構是值類型,不存在內存管理的問題。所以只須要class類型的變量聲明爲weak便可。

利用Swift的optional chaining,咱們可以很方便的檢查delegate是否爲Nil,是否有實現某個方法:

之前咱們要在Objective-C這樣檢查:

1
2
3
  if  (self.dataSource && [self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
         thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
     }

在Swift中,很是的優雅簡潔。

1
2
if  let thisSementTitle = dataSource?.titleFroSegmentAtIndex?(index){
}

新特性:

1.在Swift中,protocol變得更增強大,靈活:

2.class,enum,structure均可以遵照協議。

Extension也能遵照協議。利用它,咱們不須要繼承,也可以讓系統的類也遵循咱們的協議。

例如:

1
2
3
4
5
6
7
8
protocol myProtocol {
  func hello() -> String
}
extension String:myProtocol{
  func hello() -> String {
      return  "hello world!"
  }
}

咱們還可以用這個特性來組織咱們的代碼結構,以下面的代碼所示,將UITableViewDataSource的實現移到了Extension。使代碼更清晰。

1
2
3
4
// MARK: - UITableViewDataSource
extension MyViewcontroller: UITableViewDataSource {
// table view data source methods
}

3.Protocol Oriented Programming

隨着Swift2.0的發佈,面向協議編程正式也加入到了Swift的編程範式。Cool.

這種編程方式經過怎樣的語法特性支撐的呢?

那就是咱們可以對協議進行擴展,也就是咱們可以提供協議的默認實現,可以爲協議添加新的方法與實現。

用前面的myProtocol爲例子,咱們在Swift裏這樣爲它提供默認實現。

1
2
3
4
5
extension myProtocol{
     func hello() -> String {
      return  "hello world!"
     }
}

咱們還能對系統原有的protocol進行擴展,大大加強了咱們的想象空間。Swift2.0的實現也有不少地方用extension protocol的形式進行了重構。

面向協議編程可以展開說不少,在這裏這簡單地介紹了語法。有興趣的朋友能夠參考下面的資料:

Session 408: Protocol-Oriented Programming in Swift

IF YOU'RE SUBCLASSING, YOU'RE DOING IT WRONG.

7.Swift與Cocoa

一門語言的的強大與否,除了自身優秀的特性外,很大一點還得依靠背後的框架。Swift直接採用蘋果公司經營了好久的Cocoa框架。如今咱們來看看使用Swift和Cocoa交互一些須要注意的地方。

  • id與AnyObject

在Swift中,沒有id類型,Swift用一個名字叫AnyObject的protocol來表明任意類型的對象。

1
  id myObject = [[UITableViewCell alloc]init];
1
  var  myObject: AnyObject = UITableViewCell()

咱們知道id的類型直到運行時才能被肯定,若是咱們向一個對象發送一條不能響應的消息,就會致使crash。

咱們能夠利用Swift的語法特性來防止這樣的錯誤:

1
myObject.method?()

若是myObject沒有這個方法,就不會執行,相似檢查delegate是否有實現代理方法。

在Swift中,在AnyObject上獲取的property都是optional的。

  • 閉包

OC中的block在Swift中無縫地轉換爲閉包。函數實際上也是一種特殊的閉包。

  • 錯誤處理

以前OC典型的錯誤處理步驟:

1
2
3
4
5
6
7
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *URL = [NSURL fileURLWithPath:@ "/path/to/file" ];
NSError *error = nil;
BOOL success = [fileManager removeItemAtURL:URL error:&error];
if  (!success) {
  NSLog(@ "Error: %@" , error.domain);
}

在Swift中:

1
2
3
4
5
6
7
let fileManager = NSFileManager.defaultManager()
let URL = NSURL.fileURLWithPath( "/path/to/file" )
do  {
  try  fileManager.removeItemAtURL(URL)
catch  let error as NSError {
  print( "Error: \(error.domain)" )
}
  • KVO

Swift支持KVO。可是KVO在Swift,我的以爲是不夠優雅的,KVO在Swift只限支持繼承NSObject的類,有其侷限性,在這裏就不介紹如何使用了。

網上也出現了一些開源庫來解決這樣的問題。有興趣能夠參考一下:

Observable-Swift

KVO 在OS X中有Binding的能力,也就是咱們可以將兩個屬性綁定在一塊兒,一個屬性變化,另一個屬性也會變化。對與UI和數據的同步更新頗有幫助,也是MVVM架構的需求之一。以前已經眼饞這個特性好久了,雖然Swift沒有原生帶來支持,Swift支持的泛型編程給開源界帶來許多新的想法。下面這個庫就是實現binding的效果。

Bond

8.總結

到這裏就基本介紹完Swift當中最基本的語法和與Objective-C的對比和改進。

事實上Swift的世界相比OC的世界還有不少新鮮的東西等待咱們去發現和總結,Swift帶來的多範式編程也將給咱們編程的架構和代碼的組織帶來更來的思考。而Swift也是一個不斷變化,不斷革新的語言。相信將來的發展和穩定性會更讓咱們驚喜。這篇文章也將隨着Swift的更新而不斷更新,同時限制篇幅,突出重點。

但願這篇文章可以給各位同行的小夥伴們快速瞭解和學習Swift提供一點幫助。有疏漏錯誤的地方歡迎直接提出。感謝。

參考:

The Swift Programming Language

Apple Swift Blog

Using Swift with Cocoa and Objective-C

相關文章
相關標籤/搜索