Swiftとはどのような言語か？

※諸事情によりはてブロから転載

作成日
2014/06/03

更新日
2014/09/14

---
#Swift

##1 どんな言語？
* 読みはスイフト
* Objective-CとC言語の中間に位置する言語
* Apple曰くObjective-C Without Cとのことです
* LLVMコンパイラベース
* モダンかつObjective-Cよりも高速
* ソートでの処理速度でpython 1xとして、objective-c 2.8x , swift 3.9x
* Xcode記述時にリアルタイムに実行内容を確認できる
* 拡張子は「.swift」

##2 文法

セミコロンが要りません

コメントは以下のように従来通り

###1行コメント

    // 1行コメント  

###複数行コメント

      /* 
      * 複数行コメント 
      */

###タプル

複数の値を扱う概念です、Pythonなどでも使われています。

    (Int, String)

とするとIntとStringを扱うタプルとみなされます。  
この概念を使い返り値をタプルとすることで、複数の
返り値をまとめて返すことが可能になります。

### 整数範囲指定

「...」と「..<」を使うことで整数を範囲指定することができます
違いとしては範囲の上限を含むか、含まないかになります

* 「...」：上限を含む
* 「..<」 ：上限を含めない

```
let a = 0
let b = 5
let c = a...b //-> [0, 1, 2, 3, 4, 5]
let d = a..<b  //-> [0, 1, 2, 3, 4]
let e = 0...6 //-> [0, 1, 2, 3, 4, 5, 6]
```

### Integers

####整数値の最大値、最小値を返す

やはりObjective-Cとは違い、Int型から処理を実行しています。  
既にここから Objective-C without C が表現できているのでは  
ないでしょうか。

```
var minValue = UInt8.min  // UInt8の最小値である0を返します
var maxValue = UInt8.max // UInt8の最大値である255を返します
```

####Int／UInt

32-bit プラットフォームの Int32/UInt32と同義  
64-bit プラットフォームの Int64/UInt64と同義

####Float

32-bit 浮動小数点値

####Double

64-bit 浮動小数点値

### 変数宣言
####型無し

代入される値から型を推論します
    
```
var apple = 10
var cocoa = "cocoa"
```

####型付き

もちろん型を付けて宣言もできます。  
ここまで見るとJavaScript／TypeScriptっぽいですね

    var apple : Int = 10
    var cocoa : String = "cocoa"

####定数

変数に値を束縛します  
Scalaにも同じ概念があるようです

    let apple : Int = 10
    let cocoa : String = "cocoa"

####好きな文字が(Unicodeの対応範囲で)変数／定数として宣言できます

    let π = 3.14159
    let 你好 = "你好世界"

### 文字列

####リテラル

    "Hello world"

####比較

    var str = "apple"
    if str == "apple" {
        // "apple" と等しい
    }else{
        // それ以外の文字列
    }

####大文字変換

    var normal = "Swift"
    // UpperCase
    var upper = normal.uppercaseString //-> SWIFT

####小文字変換
    var normal = "Swift"
    // LowerCase
    var lower = normal.lowercaseString //-> swift

####数値変換

    var a = "123"
    var aNum : Int = a.toInt()!

####空文字チェック

    var str = ""
    if str.isEmpty {
        // 文字列が空です
    }else{
        // 文字列は入ってます
    }

### if文

####通常
    POP = 90 // 降水確率
    if 0 <= POP || POP < 30 {
        println("傘は必要ありません。")
    } else if 30 <= POP || POP <= 100 {
        println("傘を持っていく必要があります。")
    } else {
        println("対応していない値です")
    }

####ifスコープ内のみの変数／定数宣言

    if let accountID = searchAccountID("会員番号") {
        // アカウントIDを取得、何らかの処理を実施
        sendClient(accountID)
    } else {
        // アカウントIDが取れなかった場合
    }

### switch文

####通常

    var someVar = 30
    var result = ""
    switch someVar{
    case 10:
        result += "ten"
    case 20:
        result += "twenty"
    case 30:
        result += "thirty"
    default:
        result += "unknown"
    }
    println(result)
    //-> thirty

####範囲指定

    let count = 3_000_000_000_000
    let countedThings = "stars in the Milky Way"
    var naturalCount: String
    switch count {
    case 0:
        naturalCount = "no"
    case 1...3:
        naturalCount = "a few"
    case 4...9:
        naturalCount = "several"
    case 10...99:
        naturalCount = "tens of"
    case 100...999:
        naturalCount = "hundreds of"
    case 1000...999_999:
        naturalCount = "thousands of"
    default:
        naturalCount = "millions and millions of"
    }
    
    println("There are \(naturalCount) \(countedThings).")
    //-> There are millions and millions of stars in the Milky Way.

####パターンマッチ

    var point : (Int, Int) = (2, 2)
    switch point {
    case ("0", "0"):
        println("(0, 0) is at the origin.")
    case ("-2...2", "-2...2"):
        println("(\(point.0), \(point.1)) is near the origin.")
    default:
        println("The point is at (\(point.0), \(point.1)).")
    }

### for文

####通常

    for var index = 0; index < 3; ++index {
        println("index is \(index)")
    }
    // index is 0
    // index is 1
    // index is 2

####範囲指定

    for index in 1...5 {
        println("\(index) times 5 is \(index * 5)")
    }

####高速列挙

    let names = ["Anna", "Alex", "Brian", "Jack"]
    for name in names {
        println("Hello, \(name)!")
    }
    // Hello, Anna!
    // Hello, Alex!
    // Hello, Brian!
    // Hello, Jack!

####index省略

Swiftでは処理中のインデックスを気にする必要がないような処理では
_ を使うことにより省略して書くことができます。

    for _ in 1...3 {
        // 何らかの処理を3回実施します
    }

### メソッド

####定義
    func sayHello(personName : String) -> String{
        var greeting = "Hello, " + personName + "!"
        return greeting
    }

####呼び出し

    println(sayHello("Anna"))
    // prints "Hello, Anna!"
    println(sayHello("Brian"))
    // prints "Hello, Brian!"

####名前付き引数呼び出し

ruby2.0で導入されたものと非常に似ています

    sayHello(personName:"Annna")
    sayHello(personName:"Brian")

####可変長引数

    // Double値の平均を求める
    func arithmeticMean(numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
        return total / Double(numbers.count)
    }
    arithmeticMean(1, 2, 3, 4, 5)
    // 3.0 のDouble値が返ります
    arithmeticMean(3, 8, 19)
    // 10.0 のDouble値が返ります

####Generic定義

    func swapTwoValues<T>(inout a: T, inout b: T) {
        let temporaryA = a
        a = b
        b = temporaryA
    }

####Genericメソッド呼び出し

    var someInt = 3
    var anotherInt = 107
    swapTwoValues(&someInt, &anotherInt)
    // 変数someIntは「107」, anotherIntは「3」
 
    var someString = "hello"
    var anotherString = "world"
    swapTwoValues(&someString, &anotherString)
    // 変数someStringは「world」、notherStringは「hello」

####デフォルト引数

    func isValidService(serviceName: String , accountType: String = "none") -> Bool {
      ...
      return true
    }
    let isValid = isValidService("Picture") // isValidService("Picture", "none"')と同値

### 代入

####通常

    let b = 10
    var a = 5
    a = b
    // aの値は10になります

### enum

####定義
    enum CompassPoint {
        case North
        case South
        case East
        case West
    }

####呼び出し
    var point : CompassPoint = .East

### 配列

####リテラル
    [value 1, value 2, value 3]

####String型の配列
    var shoppingList: [String] = ["Eggs", "Milk"]

####Int型の変数から配列を生成

    var a : Int = 100
    var b : Int = 200
    var numbers = [a, b] //-> [100, 200]

### 辞書

####リテラル
    [key 1: value 1, key 2: value 2, key 3: value 3]

### Extension クラス拡張

    extension Double {
        var km: Double { return self * 1_000.0 }
        var m: Double { return self }
        var cm: Double { return self / 100.0 }
        var mm: Double { return self / 1_000.0 }
        var ft: Double { return self / 3.28084 }
    }
    let oneInch = 25.4.mm
    println("One inch is \(oneInch) meters")
    // One inch(25.4.mm) は 0.0254 meters
    let threeFeet = 3.ft
    println("Three feet is \(threeFeet) meters")
    // prints Three feet(3.ft) は 0.914399970739201 meters

### 便利な数値リテラル

    var money : Int = 2_000_000

### Initialization

initキーワード
Objective-Cでいう \- [NSObject init]
呼び出す場合は HogeClass() という風になる

### Deinitialization

deinitキーワード
Objective-Cでいうdeallocのようなもの。
classオブジェクトしか利用できない

### getのプレフィックスについて

やはりObjective-Cの理念としてメソッド名にgetのPrefixはつけていない模様

### キャスト

    var hogeNum : Int = 10
    var hogeNumStr : String = String(hogeNum)

### 継承

####親クラス
    class Vehicle {
        var numberOfWheels: Int
        var maxPassengers: Int
        func description() -> String {
            return "\(numberOfWheels) wheels; up to \(maxPassengers) passengers"
        }
        init() {
            numberOfWheels = 0
            maxPassengers = 1
        }
    }

####子クラス
    class Bicycle: Vehicle {
        init() {
            super.init()
            numberOfWheels = 2
        }
    }

####メソッドオーバーライド

    class Car: Vehicle {
        var speed: Double = 0.0
        init() {
            super.init()
            maxPassengers = 5
            numberOfWheels = 4
        }
        override func description() -> String {
            return super.description() + "; "
                + "traveling at \(speed) mph"
        }
    }

####プロパティオーバーライド

    class SpeedLimitedCar: Car {
        override var speed: Double  {
            get {
                return super.speed
            }
            set {
                super.speed = min(newValue, 40.0)
            }
        }
    }

####オーバーライド防止

@final修飾子をつけることによってサブクラスがオーバーライドすると
コンパイラがエラーにしてくれます

### クラス

####定義

    class Hoge {
        // Hoge コンストラクタ
        init(){
            // 生成処理
        }
        // Hoge デコンストラクタ
        deinit(){
            // 破棄処理
        }
    }

####プロパティ

プロパティは定義して初期値を設定しない場合は
コンストラクタ内で初期値を設定しなければエラーとなる

#####初期値を設定する場合
    class Car {
        var numberOfWheels : Int = 4
    }

#####初期値を設定しない場合
    class Car {
        var numberOfWheels : Int
        init(){
            numberOfWheels = 4
        }
    }

ゲッター、セッターも定義ができる    

#####プロパティ内でゲッター定義
    class Car {
        var numberOfWheels : Int {
            get {
                return 4
            }
        }
    }

####呼び出し

    var hoge : Hoge = Hoge()

####クラスメソッド定義

    class Fuga {
        class func some() -> String {
            return "did it."
        }
    }

####クラスメソッド呼び出し

    Fuga.some() //-> did it.

### クロージャ

####通常
    let sum = {
        (a:Int, b:Int)->Int in
        return a+b
    }
    sum(1+2) //-> 3

####返り値型省略

    let sum = {
        (a:Int, b:Int) in
        return a+b
    }
    sum(1+2) //-> 3

### タイプ

####独自タイプ定義

    typealias Vector = (Double, Double, Double)
    let playerVector = (10, 20, 50)

### 名前空間

ProjectのBuildTargetごとに名前空間が付く

### is 演算子

Objective-Cでいうところの
  
* \- [NSObject isKindOfClass]
* \- [NSObject isConfirmToProtocol]

そのオブジェクトがクラスまたはプロトコルに準拠しているかをチェックします

    if object is UILabel {
        // ラベルです
    } else {
        // ラベルではありません
    }


##3 C言語との連携

### C言語のプリミティブ型のSwift対応型表

| C言語型 | Swift型 |
| :-- | :-- |
| bool | CBool |
| char, signed char| CChar |
| unsigned char| CUnsignedChar |
| short | CShort |
| unsigned short | CUnsignedShort |
| int | CInt |
| unsigned int | CUnsignedInt |
| long | CLong |
| unsigned long | CUnsignedLong |
| long long | CLongLong |
| unsigned long long | CUnsignedLongLong |
| wchar_t | CWideChar |
| char16_t | CChar16 |
| char32_t | CChar32 |
| float | CFloat |
| double | CDouble |

### C言語対応Swift型をSwift型に変換

| C言語対応Swift型変数 | 変換 | 変換Swift型 |
| :-- | :-- | :-- |
| cValue : CBool | Bool(cValue) | Bool |
| cValue : CChar |  String.fromCString(UnsafePointer<CChar>(cValue)) | String |
| cValue : CUnsignedChar | String.stringWithCString(UnsafePointer(cValue), encoding: someEncoding) | String |
| cValue : CShort | Int16(cValue) | Int16 |
| cValue : CUnsignedShort | UInt16(cValue) | UInt16 |
| cValue : CInt | Int32(cValue) | Int32 |
| cValue : CUnsignedInt | UInt(cValue) | UInt |
| cValue : CLong | Int(cValue) | Int |
| cValue : CUnsignedLong | UInt(cValue) | UInt |
| cValue : CLongLong | Int64(cValue) | Int64 |
| cValue : CUnsignedLongLong | UInt64(cValue) | UInt64 |
| cValue : 

### C言語のポインタ型のSwift対応型表

| C言語ポインタ型 | Swift型 |
|:--|:--|
| const void * | CConstVoidPointer |
| void * | CMutableVoidPointer |
| const 型 * | CConstPointer<型> |
| 型 * | CMutablePointer<型> |
| void * | COpaquePointer |
| 型 * | UnsafePointer<型> |
| 型 * const * | CConstPointer<型> |
| 型 * __strong * | CMutablePointer<型> |
| 型 ** | AutoreleasingUnsafePointer<型> |


## 4 Objective-Cとの連携／比較

### NS_ENUM定義とSwiftのenum定義比較

#### Objective-C

    typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
       UITableViewCellStyleDefault,
       UITableViewCellStyleValue1,
       UITableViewCellStyleValue2,
       UITableViewCellStyleSubtitle
    };

#### Swift

    enum UITableViewCellStyle: Int {
        case Default
        case Value1
        case Value2
        case Subtitle
    }

***