Swift3.0を学ぶにあたって知っておきたい基礎文法(前編)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Swift3.0を学ぶにあたって、言語的に必要そうな部分を広く浅く一覧にしてみました。
今回は、変数、定数、型を中心とした内容です。

開発環境

基礎文法ではありませんが、まずはSwiftを試してみる環境について。

XCode

Apple公式の統合開発環境 (IDE) 。
SwiftでiOSアプリを作るなら必須。
https://developer.apple.com/xcode/jp/
icon-xcode-6

IBM Swift Sandbox

ブラウザ上でSwiftのコードを試せる。手軽。
まずはSwiftという言語をさわってみたいという方にオススメ。
https://swiftlang.ng.bluemix.net

IBM_Swift_Sandbox

コメント

//は単行のコメント。
/* から */ の囲まれた部分がコメント(複数行OK)。

// 単行のコメント

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

変数、定数

定数(let)

一度、値を設定したら変更は出来ない。

let word = "apple"
※ 以下はエラーになる
let word = "apple"
word = "grape" // NG(エラー)

変数(var)

値を変更出来る。

var word = "apple"
word = "grape" // OK
値を変更する必要のない場合

XCodeではWarningが出るので、変更する必要が無いものは定数(let)にする。

swift error sample

型の指定は定数/変数の右に :型名 で設定する。

let name: String = "hoge"
let code1: Int = 1234
let code2: Float = 10.1
let code3: Double = 1.23
var isAdmin: Bool = false

String, Int, Float, Double, Bool が型に該当

型推論

Swiftでは型を定義しなくても推論が行われる

let name = "hoge"         // String
let code1 = 1234          // Int
let code2 = 10.1          // Double
let code3 = 1.23          // Double
var isAdmin = false       // Bool

例えば10.1のような小数を設定した場合、指定しないとDoubleとして扱われる。
Floatなど、デフォルトの型推論以外の型にしたい場合は個別に設定する必要がある。

タイプエイリアス(typealias)

型を別名で定義できる

import Foundation

typealias Age = Int
let age: Age = 20

typealias CompletionHandler = (NSError?) -> Void
func loadItemWith(completion: CompletionHandler) { ... }

型チェック(is)

インスタンスに対してチェックを行う

class Animal {}
class Cat: Animal {}
class Dog: Animal {}

let cat: Animal = Cat()
print( cat is Cat ) // true
print( cat is Dog ) // false

キャスト(as, as!, as?)

class Animal {}
class Cat: Animal {}
class Dog: Animal {}

let cat: Animal = Cat()
let dog = Dog()

let type1 = cat as Cat    // エラー(ダウンキャストにあたるため)
let type2 = dog as Animal  // OK
let type3 = cat as? Cat    // OK (Optional(Cat))
let type4 = cat as? Dog    // nil
let type5 = cat as! Cat    // OK
as アップキャストなどキャストが成功すると保証される場合に使用
as! 強制ダウンキャストの場合に使用
as? ダウンキャストが成功するか分からない場合に使用(戻り値はOptional失敗するとnil)

オプショナル型(Optional)

SwiftのStringなどの通常の型にはnil(空の状態)を保持出来ない。オプショナル型にすることとでnilを入れることが出来る。
たとえばStringのオプショナルは下記、

var aaa: Optional<String>
aaa = "ABC" // {Some: "ABC"}

↓ ただし、これを省略して書くことが出来る。(通常こちらで書く)

var aaa: String?
aaa = "ABC" // {Some: "ABC"}

型の後ろに?をつける。String?はOptionalの省略形。 オプショナルは宣言時に値を入れないと自動的にnilとなる。

アンラップとは?

Optional型(String?)は下記のコードのようにString型として扱えないためアンラップで扱えるようにする。

var aaa: String?
aaa = "ABC"
let bbb: String = aaa // エラーになる
print(aaa.appending("!!")) // エラーになる

暗黙的なオプショナル型(ImplicitlyUnwrappedOptional)

アンラップとは?のところで、オプショナル型の値を使おうとした時にアンラップが必要と書いたけど、暗黙的なオプショナル型にすると自動でアンラップが起こってそのまま使える。

var ccc: ImplicitlyUnwrappedOptional<String>
ccc = "ABC"
let bbb: String = ccc // 自動的にアンラップされるのでOK

こちらも省略して書くことが出来る。(通常こちらで書く)

var ccc: String!
ccc = "ABC"
let bbb: String = ccc // 自動的にアンラップされるのでOK

型の後ろに!をつける。String!はImplicitlyUnwrappedOptionalの省略形。 オプショナルは宣言時に値を入れないと自動的にnilとなる。

暗黙的なオプショナル型の注意点!

使用時に自動的にアンラップされて元の型になる(そのまま使える)一方、 もし使用時にnilだったら実行時にエラーになる。キケン。

var ccc: String!
let bbb: String = ccc // cccに値が無いためアプリがクラッシュする

Optional Binding (if let、guard let)

nilチェックしてnilでなければ元の型を取り出す。
if let 〜 はnilでない場合if内で取り出した値を使うことができ、
guard letelse はnilの場合guardの中に入り以降の処理を行わない。取り出した値をguard以降で利用できる。

var aaa: String?
aaa = "ABC"

if let tmp = aaa {
   // aaaがnilでなければここにくる
   // このif文の中でtmpという定数が使える
   print(tmp) // "ABC"
}

guard let tmp2 = aaa else {
    // aaaがnilならここにくる(以降の処理を行わない)
    return
}
// aaaがnilでなければここにくる
// 以降tmp2という定数が使える
print(tmp2) // "ABC"

if letはif内でのみアンラップした値が有効だが、guard letは以降のメソッド内で利用が可能となる。

Swift3からの変更点

if let で Optional を アンラップしてからその値を判定する際に、以前はwhereを使っいたが、カンマで区切って条件を書けるように。(SE-0099)

// before
if let a = a, b = b where a == b { }
// after
 if let a = a, let b = b, a == b { }

Optional Chaining(?)

変数名の後ろにを付けると元の型のメソッドなどを扱えるようになる。 結果もOptional型。nilの場合は無視される(エラーで落ちない)

var aaa: String?
aaa = "ABC"
print(aaa?.appending("!!")) // エラーにならない

Forced Unwrapping(!)

オプショナル変数名の後ろに!を付けると強制的に元の型として扱える。 結果は元の型になっている。nilの場合は実行時にエラーになる。キケン。

var aaa: String?
var eee: String?
let bbb: String = aaa! // OK
print(eee!.appending("!!")) // NG、アプリがクラッシュする

オプショナル型の変数の定義するところの,!と アンラップ時の?,!は別物です。(混同しないように気をつけよう)