Swift4基礎知識

# 変数

## var,let
varが変数
letが定数

## オプショナル型

Swiftには「オプショナル型「と「非オプショナル型」というものがあり、違いは下記。
・オプショナル型はnilの代入を許容することができる
・非オプショナル型はnilの代入を許容することができない

オプショナル型の変数には最後に「?」か「!」をつけます。

```swift

// 例えばStringにnilを代入しようとするとエラーが出ます
$ var a: String = nil
# => error: nil cannot initialize specified type 'String'

// 「?」をつければエラーは出ません
$ var a: String? = nil

// Optionalとついています
$ var a: String? = "hoge"
$ print(a)
# => Optional("hoge")

// 宣言時はnilの状態
$ var a: String?
$ print(a)
# => nil
```

オプショナル型の変数を使用するときはnilか否かを判別して使用します。

```swift

let str: Optional<String> = nil

if str　!= nil {
    print(s!) // !でアンラップしてから使う
}


if let value = str {
    print(value)
}

print(str ?? "nilです")

```

# 関数

## 関数の基本形
まずは基本から。

```swift
// func double(引数名: 型) -> 戻り値の型 {...}
func double(num: Int) -> Int {
  return num * num
}

print(double(num: 3))

// _をつけると引数名を省略できる
func double(_ num: Int) -> Int {
  return num * num
}

print(double(3))
```

## 外部引数と内部引数
関数の中と外で違う引数名をつけられる。

```swift
// numが外部引数でageが内部引数
func person(name: String, num age: Int) {
  print(name)
  print(age)
}

person(name: "太郎", num: 10)

// 外部引数の省略
func person(_ name: String, _ age: Int) {
  print(name)
  print(age)
}

person("太郎", 10)
```

## デフォルト引数

```swift

func person(name: String = "太郎") {
  print(name)
}

person()
person(name: "花子")
# -> 太郎
# -> 花子
```

## インアウト引数
関数内での変数の再代入を関数外で反映させるにはインアウト引数を使う。

```swift
func name(name: String) {
  name = "花子" // 引数は関数内では定数になるので再代入はエラーになります
  print(name)
}

// 再代入を可能にするにはinout引数を使います
func name(name: inout String) {
  name = "花子"
  print(name)
}

var name: String = "太郎" // nameに太郎を代入
name(name: &name) // &を忘れない
# -> 花子
// 以降、name変数の中身は花子になっている

```

## 可変長引数　
可変長引数は任意の個数の値を受け取ることができる。
...をつける。

```swift

func fruits(fruits: String...) {
  print(fruits)
  print(fruits[0])
}

fruits(fruits: "apple", "banana", "orange")

// 関数内部ではArray<Element>として扱われる
# -> ["apple", "banana", "orange"]
# -> apple
```

# 型
・構造体
・クラス
・列挙型

## 構造体

```swift
// Personという構造体を定義
struct Person {
  var name = "太郎"

  func greet() {
    print("hi!")
    print(self) // selfでインスタンス自身にアクセスできる(selfは省略可)
    print(self.name)
    print(name)
  }
}

var p = Person() // Personをインスタンス化
p.greet()

# -> hi!
# -> Person(name: "太郎")
# -> 太郎
# -> 太郎
```

## クラス

```swift

class Human {

  func greet() {
    print("hi!")
  }
}

// classは継承が可能
class Student: Human {
  // overrideで上書きも可能
  override func greet() {
    super.greet() // 親クラスのgreet()の呼び出し
    print("hello")
  }
}
```

## 列挙型

# プロトコル
**型がどのようなメソッドやプロパティを持つかを示す**

**【ポイント】**
プロトコルでは定義のみを行い、処理は実装しない。
こういった変数やメソッドを使いますよ〜といった宣言のみ。
プロパティの定義についてはvarが使用でき、letは使用できない。

```swift
// Humanプロトコルを定義
protocol Human {
  // プロパティを定義
  var age: Int { get }
  var name: String { get }

  // メソッドを定義
  func printAge()
  func printName()
}

// プロトコルの処理の実装は採用元で行う。
// プロトコルの中で定義したメソッドやプロパティは必ず実装しなければならない。
// 実装していない場合のエラー: does not conform to protocol
class Student: Human {
  var age: Int {
    get{
      return 0
    }
  }

  func printAge() {
  }
}
```

## プロトコルを拡張する

```swift
// プロトコルを定義
protocol Greet {
}

// プロトコルを拡張し、helloメソッドを追加
extension Greet {
    func hello() {
        print("hello!")
    }
}

// プロトコルを採用する
class User: Greet {
}

var user1 = User()
user1.hello() // 拡張で追加したhello()が使えるようになる
```

# デリゲート(Delegate)

あるオブジェクトの処理を別のオブジェクトに代替する。

Delegate = 委譲、委ねる

Delegateに関しては実際のiOSプロジェクトを使ったほうがわかりやすいと思うので新規でプロジェクトを作成しましょう。

ViewController.swiftの中身です。

```swift

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()  
    }
}
```

UITextFieldDelegateを追加しましょう。

```swift

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()  
    }
}
```

UITextFieldDelegateの実態はプロトコルです。
Xcode上でoptionキーを押しながら「UITextFieldDelegate」をクリックしてください。
下記のようなポップアップが表示されるはずです。

これを見れば、どのメソッドがどのタイミングで呼び出されるかがわかります。

<img width="672" alt="スクリーンショット 2018-10-21 14.08.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/201127/3992c577-5d4c-cbef-43c9-9d3f76fdd736.png">

ここで試しに「textFieldShouldReturn」というメソッドを使ってみます。
textFieldShouldReturnはキーボードのreturnキーが押されたタイミングで呼び出されるメソッドです。

```swift
import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()  
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        print("returnが押された")
        return true
    }
}
```

<img width="216" alt="スクリーンショット 2018-10-21 14.15.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/201127/e19baf5f-6ef2-34fd-9629-d9296ce28fc6.png">