PHPプログラマのためのSwift言語入門

#概要
普段はPHPプログラマで、これからiOSアプリ開発をしていきたい人向けに、Swift言語の基本をまとめていく。

#動作環境
OS X El Capitan 10.11.4
Xcode7.3（2016年5月現在の最新バージョン、Swift2.2対応） 
Xcodeは**App Store版**でも良いが、**dmg版（以下のURLからダウンロード）**を推奨。
https://developer.apple.com/downloads/

参考
[複数バージョンのXcodeを入れる方法と各Xcodeに対応するSwiftのバージョン一覧](http://qiita.com/kentyama/items/bfa67ed8f03543ff848e)

#文法の勉強はプレイグラウンドを使う
Get started with a playgroundをクリック
![スクリーンショット 2016-05-03 5.27.08.png](https://qiita-image-store.s3.amazonaws.com/0/121962/e7c4a47e-e9f6-b37a-f13a-87eb06110135.png)

コンパイル不要ですぐに動作確認出来る
![スクリーンショット 2016-05-03 5.26.01.png](https://qiita-image-store.s3.amazonaws.com/0/121962/2f471f0a-e54e-f016-1552-b00efe2d0507.png)

#文末のセミコロンは不要
PHP

```
echo 'test';
```
Swift

```
print("test")
```

#文字列にシングルクォートは使えないのでダブルクォートで書く
PHP

```
echo 'test';
```
Swift

```
print("test")
```

#定数の宣言
PHP

```
//クラス外定数の場合
define('INDEX_NUMBER', 1);

//クラス内定数の場合
const INDEX_NUMBER = 1;
```
Swift

```
//let 定数名：型名（IntやStringなど） = 値

let n:Int = 100
let str:String = "hello"

//型名省略可能
let n = 100
let str = "hello"

//出力する場合
print(n) //100
print(str) //hello
```

#変数の宣言
PHP

```
//クラス外変数
$a = 1;

//クラス内変数
private $number;
```
Swift

```
//var 定数名：型名（IntやStringやBoolなど） = 値

var n:Int = 100
var str:String = "hello"
var result:Bool = true

//型名省略可能
var n = 100
var str = "hello"
var result = true

//出力する場合
print(n) //100
print(str) //hello
print(result) //true
```
#変数の埋め込み
PHP

```
$str = 'world';
echo "hello $str"; //hello world
```
Swift

```
//バックスラッシュ（変数）

var str = "world"
print("hello \(str)") //hello world
```
#インクリメントとデクリメント
PHP

```
$n = 0;
$n++; //インクリメント
$n--; //デクリメント
echo $n;　//0
```
Swift

```
var n = 0
n += 1 //インクリメント（++演算子はSwift3系から使えなくなるのでこのような書き方になる）
n -= 1 //デクリメント（--演算子はSwift３系から使えなくなるのでこのような書き方になる）
print(n) //0
```
#NULLとnil
PHP

```
$var = null;
var_dump($var); //NULL
```
Swift

```
var str:String? = nil //型名にクエスチョンマークをつけることでnilの代入が可能となる
print(str) //nil
```

#繰り返し処理
PHP

```
for ($i=0; $i<10; $i++) {
    echo "test\n";
}
```
Swift

```
//for　変数　in　レンジや配列や辞書
for i in 1...10 {
    print("test \(i)")
}

//for　変数を使わない場合はアンダースコア in レンジや配列や辞書
for _ in 1...10 {
    print("test")
}
```
#配列定数及び配列変数の宣言
PHP

```
$numberArray = array(11,22,33);
$strArray = array("test","hello","world");
```
Swift

```
//配列定数
let number:[Int] = [11,22,33]
//配列変数
var str:[String] = ["test","hello","world"]
```
#配列の初期化
PHP

```
//配列の初期化
$numberArray = array();
//初期化された配列に値を代入
$numberArray = array(11,22,33);
```
Swift

```
//配列の初期化
var number = [Int]()
//初期化された配列に値を代入
number = [11,22,33]
```
#配列の要素を取り出す
PHP

```
$numberArray = array(11,22,33);

foreach ($numberArray as $number) {
    echo "$number\n";
}
```
Swift

```
var number:[Int] = [11,22,33]
for i in number {
    print(i)
}
```
#辞書定数及び辞書変数の宣言
PHP

```
$numberArray = array("aaa"=>11,
                     "bbb"=>22,
                     "ccc"=>33
               );
```
Swift

```
//辞書定数
let number:[String:Int] = ["aaa":11,"bbb":22,"ccc":33]
//辞書変数
var number:[String:Int] = ["aaa":11,"bbb":22,"ccc":33]
```
#辞書の初期化
PHP

```
$numberArray = array();
$numberArray = array("aaa"=>11,
                     "bbb"=>22,
                     "ccc"=>33
               );
```
Swift

```
var number = [String:Int]()
number = ["aaa":11,"bbb":22,"ccc":33]
```
#辞書の要素を取り出す
PHP

```
$numberArray = array("aaa"=>11,
                     "bbb"=>22,
                     "ccc"=>33
               );

foreach ($numberArray as $str => $number) {
    echo "$str $number\n";
}
```
Swift

```
var number:[String:Int] = ["aaa":11,"bbb":22,"ccc":33]

for (key,value) in number {
    print("\(key) \(value)")
}
```
#Swiftのオプショナル型のラップとアンラップ
Swift

```
var str:String? = "hello" //型名に?をつけてオプショナル型にラップする
print(str)  //Optional("hello")
print(str!) //hello 変数の最後に!をつけてアンラップする
```
#Swiftの辞書の値はオプショナル型
Swift

```
var number:[String:Int] = ["aaa":11,"bbb":22,"ccc":33]
print(number["aaa"])  //Optional(11)
print(number["aaa"]!) //11 エクスクラメーションをつけてアンラップして取り出す
```
#値がnilの可能性のあるデータをオプショナル型の配列で保管する（なお辞書では値がnilの場合は無視されるので保管できない）
Swift

```
var array:[String?] = ["hello",nil,"world"]

for i in array {
    print(i)
}

//Optional("hello")
//nil
//Optional("world")
```

#整数変換
Swift

```
let str = "123"  //String型
let n = Int(str) //失敗した場合はnilが返却される(型名?は省略可能)
print(n)  //Optional(123) 失敗した場合nil返却なのでオプショナル型が返却される
print(n!) //123
```
#オプショナルバインディング（optional型のnil判定）
Swift

```
var array:[String?] = ["123",nil,"789"]

for data in array {
    if let d = data { //nilならfalse、nilではないならアンラップされた値を代入
        print(d.dynamicType) //String アンラップされていることがわかる
        print("\(Int(d)!) \(Int(d)!.dynamicType)") //123 Int,789 Int
    } else {
        //nilのときの処理
    }
}
```
#タプル（複数の異なる型の値をひとまとめにする）
Swift

```
var tp = (name:"Kentaro Yamada", age:20)
print(tp.name)
print(tp.age)
```
#enum（マジックナンバーを防ぐためにenumを使う場面がある）
Swift

```
enum OS:String {
    case Windows = "Windows"
    case iOS     = "iOS"
    case Android = "Android"
}

print(OS.Windows) //OS.Windowsの処理を書く（enumはSwitch分岐との相性が良い）
print(OS.Windows.rawValue) //デフォルトの値を持たせることができる
```
#関数
Swift

```
//戻り値なし
func hello(str:String) {
    print(str)
}
hello("hello") //hello


//戻り値あり
func world(str:String) -> String {
    return str
}
var str = world("world")
print(str) //world


//複数の戻り値
func helloWorld(name:String) -> (name:String, age:Int) {
    let age = 12
    return (name,age)
}
var ret = helloWorld("Kentaro Yamada")
print(ret.name) //Kentaro Yamada
print(ret.age)  //12

//複数の引数
func helloWorld2(name:String, age:Int) -> (name2:String, age2:Int) {
    return (name,age)
}
var ret2 = helloWorld2("Kentaro Yamada",age:12) //第2引数には引数名をつける必要有
print(ret2.name2) //Kentaro Yamada
print(ret2.age2)  //12

//複数の引数(外部名あり)
func helloWorld2(n name:String,a age:Int) -> (name2:String, age2:Int) {
    return (name,age)
}
var ret2 = helloWorld2(n:"Kentaro Yamada", a:12)
print(ret2.name2) //Kentaro Yamada
print(ret2.age2)  //12
```
#クロージャの基本
Swift

```
func fc(n:Int) -> Int {
    return n * 2
}

func clsr(f:(Int)->Int, n:Int) {
    print(f(n))
}
clsr(fc,n:10) //20
```
#クラスの基本
Swift

```
class MyData {
    
    var name:String = ""

    func hello(){
        print("hello \(name)")
    }
}

var obj = MyData()
obj.name = "Kentaro Yamada"
obj.hello() //hello Kentaro Yamada
```

#コンビニエンスイニシャライザ
Swift

```
class Test {
    
    var name:String = ""
    var age:Int = 0
    
    //指定イニシャライザ
    init(name:String, age:Int) {
        self.name = name
        self.age  = age
    }
   
    convenience init () {
        self.init(name:"noname", age:0)
    }
    
    convenience init (name:String) {
        self.init(name:name, age:0)
    }

    func hello(){
        print("\(name) \(age)")
    }
}

var test = Test(name:"Kentaro Yamada", age:20)
test.hello()  //Kentaro Yamada 20

var test2 = Test(name:"Kentaro Yamada")
test2.hello() //Kentaro Yamada 0

var test3 = Test()
test3.hello() //noname 0
```

#Computedプロパティ
Swift

```

class Test {
    
    private var name:String = ""
    private var age:Int = 0
    
    //Computedプロパティ
    var getName:String {
        get {
            return self.name
        }
        set {
            self.name = newValue
        }
    }
    
    init(name:String, age:Int) {
         self.name = name
        self.age  = age
    }
    func hello(){
        print("\(name) \(age)")
    }
}

var test = Test(name:"Kentaro Yamada", age:20)
test.hello()  //Kentaro Yamada 20
print(test.getName) //Kentaro Yamada
test.getName = "aaa"
print(test.getName) //aaa
```

#プロパティオブザーバー
Swift

```
class Test {
    
    //プロパティオブザーバー（書き換えの前後を監視する）
    var name:String = "" {
        willSet(name){
            print("willSet \(name)")
        }
        didSet {
            print("didSet \(name)")
        }
    }
    var age:Int = 0
    
    init(name:String, age:Int) {
         self.name = name
        self.age  = age
    }
    func hello(){
        print("\(name) \(age)")
    }
}

var test = Test(name:"Kentaro Yamada", age:20)
test.hello()  //Kentaro Yamada 20
test.name = "hello"
print(test.name) //hello
test.hello() //hello 20
```