プログラミング言語Swift日本語チュートリアル ~ 前編(Apple公式ドキュメントSwift Tour±α)

このドキュメントは、

  • Ruby/C++などでプログラミング経験がある人が
  • Swiftを初めて勉強するときに、
  • インストールから始めて、
  • 標準ライブラリを調べながらなら一通りはコーディング出来るようになる

ことを目的としたチュートリアルの前編です。

プログラミング言語Swift日本語チュートリアル ~ 後編(Apple公式ドキュメントSwift Tour±α) - こんにゃくマガジン
と併せてApple公式SwiftドキュメントのThe Swift Programming Language: A Swift Tour相当(翻訳ではないです)±αな内容になっています。

後編の内容は、SwiftでのiOSアプリ開発はじめの一歩、クラス、列挙、構造体、ジェネリクス、簡単なネットワークライブラリの使い方となっています。

Swiftチュートリアル

公式サイト紹介

Apple公式Swiftサイト https://developer.apple.com/swift/
f:id:knj4484:20140613214723p:plain
とても楽しそうな雰囲気ですね!

Xcode 6 betaをダウンロードする

  1. iOS Developer Programにメンバー登録したApple IDでログインしておく
  2. ここに行く https://developer.apple.com/devcenter/ios/index.action
  3. Xcode 6 betaのDownload Xcodeボタンを押してしばらく待つ

f:id:knj4484:20140613212947p:plain

インストール

  1. ダウンロードしたファイルxcode_6_beta.dmgをダブルクリックして、しばらく待つ
  2. 出てきたウインドウで左のXcodeアイコンを右のAppアイコンにドラッグ&ドロップ

f:id:knj4484:20140613211107p:plain

Xcode 6 betaを起動する

初回起動はわりと時間がかかります

  1. Internetからダウンロードしたアプリうんぬん > Open
  2. Licence Agreement > Agree
  3. These application must be quit before installation can continued > Quit All
  4. Welcome to Xcode > Get started with a playgroundf:id:knj4484:20140615103504p:plain
  5. Save as : MyPlayground > Create
  6. コンソール出力エリアを表示:メニューからView > Assitant Editor > Show Assistant Editorf:id:knj4484:20140615102240p:plain
  7. 左側にprintln("hello swift")と入力
    • 右側Consolo Outputのところにhello swiftと出力されましたか?f:id:knj4484:20140615102853p:plain

このようにplaygroundという機能でswiftのコードを試すことが出来ます。

もう一度playgroundを作りたい場合は、
メニューからWindow > Welcome to Xcode
で出来ます。

以前のXcodeが起動している状態で6betaを起動するとうまく行かないかもしれません

コマンドラインSwiftシェルを使う

~/.bash_profileに下記を追加しておく

PATH=/Applications/Xcode6-Beta.app//Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH

Terminalを起動して、swiftコマンドを動かす

$ swift  -sdk $(xcrun --show-sdk-path --sdk macosx)
(略)
Welcome to Swift!  Type :help for assistance.
  1> 

Swiftプロンプトで何か実行してみる

  1> println("Hello Swift!")
Hello Swift!
  2> 

control + D で終了

-integrated-replオプションというのもあり、同じような使い方が出来る(違いはなんだろう?)

$ swift -integrated-repl -sdk $(xcrun --show-sdk-path --sdk macosx)
Welcome to swift.  Type ':help' for assistance.
(swift) for i in 1..3 {
          println(String(i))
        }
1
2

コマンドラインSwiftファイルを処理する

-iオプションでコンパイル結果をそのまま実行

$ swift -i foo.swift

swiftコマンドにファイル名を渡して実行ファイルを作る

$ swift foo.swift 
$ ./foo

コメント、定数、変数、型、出力、文末セミコロン

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

var myVar = 42
myVar = 50
let myConst = 42
myConst = 1 // => error: cannot assign to 'let' value 'myConst'
let implicitDouble = 70.0
let explicitDouble: Double = 70

let errorCode = 94
"error code: " + errorCode // => error: could not find an overload for '+' that accepts the supplied arguments
println("error code: " + String(errorCode)) 
  • //以降はコメントになる
  • /* */で複数行をコメントにできる。これは入れ子にもできる
  • 定数はletで定義する。変数はvarで定義する。
  • 変数の後ろにコロンで区切って型を指定することが出来る
  • 型を指定しなくても良い場合もある
    • 定数や変数を初期化するときに値から型が決められる場合など
  • 値が暗黙に他の型に変換されることは決してない
    • 他の型に変換する必要がある場合、明示的に所望の型のインスタンスを作る
  • printlnまたはprintで出力できる(printは改行なし)
  • 文末を表すセミコロンは普通は書かない
    • 一行に2文書くときや入れたいときだけ入れれば良い

コマンドライン引数を使う

for i in 1..C_ARGC {
    let arg = String.fromCString(C_ARGV[Int(i)])
    println(arg)
}
$ swift -emit-executable try-arg.swift 
$ ./try-arg aaa bbb
aaa
bbb

文字列

var name = "Swift" + " " + "Programming"
name += " Language"
countElements(name)

let boyCount = 3
let girlCount = 5
println("There are \(boyCount + girlCount) children.")
  • 文字列リテラルはダブルクオートで囲む
  • 文字列の連結には+演算子を使う
  • 文字列オブジェクトに文字列を追加するには+=演算子を使う
  • 文字列の長さはグローバル関数countElementsで分かる
  • 文字列中に値を含めるため簡単な書き方は、括弧に挟んで値を書き、括弧の前にはバックスラッシュを書く

配列

var colours = ["red", "black", "white", "blue"]
let names = String[]() // 空配列

colours[0] = "pink"
colours += "grey"
colours.count

for colour in colours {
    println(colour)
}
  • 配列はブラケットを使って定義する
  • 空の配列は、初期化子構文で定義する
  • 配列の要素にアクセスするには、インデックスをブラケット中に書く
    • インデックスはゼロ始まり
  • 配列の要素数countプロパティー
  • 要素追加は+=演算子
  • 要素をイテレートするにはfor-inを使う

dictionary

var petCounts = ["dog": 2, "cat": 3]
var wordCounts = Dictionary<String, Int>() // 空ハッシュ

wordCounts["dog"] = petCounts["dog"]

wordCounts.count
wordCounts.keys
wordCounts.values

for (pet, count) in petCounts {
  println(pet + ":" + String(count))
}
  • ハッシュはブラケットを使って、キーとバリューをコロン区切りにして定義する
  • 空ハッシュは、初期化子構文で定義する
  • ハッシュの要素にアクセスするには、キーをブラケット中に書く
  • 素数countプロパティー
  • キー一覧の取得はkeysプロパティー
  • 値一覧の取得はvaluesプロパティー
  • ハッシュの要素をイテレートするにはfor-inを使う

真偽値

var endFlag : Bool = false
endFlag = true
  • 型を指定する場合は、Boolと書く
  • trueまたはfalseどちらか(小文字表記のみ可)の値を持つ

関数の定義と呼び出し - 入門

func createMessage(title: String, body: String) -> String {
    return "title: \(title)\nbody: \(body)"
}
createMessage("task", "mail John")

func createMessage2(title t: String, #body: String) -> String {
    return "title: \(t)\nbody: \(body)"
}
createMessage2(title: "task", body: "call John")
  • 関数を定義するためにfuncを使う
  • パラメーターの後ろに->につづけて関数の戻り値の型を書く
  • 関数に括弧に入れた引数リストを続けて関数呼び出しをする
  • パラメーター名は呼び出し側で使う名前も指定できる
    • 呼び出し側と関数内部で使う名前をスペース区切りで指定できる
    • 関数内部の名前と同じでよければ、#をつけておく

条件分岐 if、三項演算子

func rank(score : Double) -> String {
    if (score > 90) {
        return "A"
    } else if score > 70 {
        return "B"
    } else {
        return "C"
    }
}

let score = 99
score > 90 ? "OK" : "NG"
  • 条件前後の括弧は書かなくても良い。本体前後の括弧は必須
  • if文の条件はブール値(あるいは後述のオプショナル値)でなければならない
    • 数値がブール値に型変換されたりしない。if score {}みたいなコードはエラーである
  • 三項演算子も使える

オプショナル値

値があるかもしれないし、ないかもしれないことを表すために、オプショナル値を使う

func createMessage(optionalTitle : String?, optionalContent : String?) -> String? {
    var message = ""
    if optionalTitle {
        message += "title: " + optionalTitle! + "\n"
    } 
    if let content = optionalContent {
        message += "content: " + content
    }

    if message == "" {
        return nil
    } else {
        return message
    }
}
  • オプショナル値型であることを表すために、型名に?を付ける
  • 値がないことを表すのにnilを使う(Nilとかnullとかはない)
  • if文でオプショナル値に値があるか知ることができる。
    • あればtrue、なければfalse扱い
  • 値を持つオプショナル値は!を付けることで値を取り出せる
  • if let tmpVar = OptionalVar 構文でオプショナル値のありなし判定と同時に値を変数に束縛できる(Optional Bindingという)
func messageCount(optionalMessages: Array<String>?) -> Int? {
    return optionalMessages?.count 
    // => optionalMessages!.count または nil
}

func lastItem(items : Array<Int>?) -> Int? {
  return items?[items!.count - 1]
}
  • オプショナル値を利用する時には、メソッドやプロパティーや[]などの操作の前に?を書くことが出来る
    • もし、?の前の値がnilであれば、
      • ?以降のもの全てが無視さる
      • 全体の式の値はnilである。
    • ?の前の値がnilでなければ、
      • オプショナル値はunwrapされる
      • ?以降の全てがunwrapされた値に対して作用する
    • いずれにしても、全体の式の値はオプショナル値である

条件分岐 switch

func evaluate(diff : Int) -> String? {
    switch diff {
    case 100:
        return "max"
    case let x where 0 < x && x < 100:
        return "up"
    case 0:
        return "-"
    case let x where x < 0:
        return "down"
    default:
        return nil
    }
}
  • switchでは(整数値の等値チェックに限らず)任意の種類のデータと様々な比較演算子が利用できる
  • マッチしたcaseの中のコード実行後には、プログラムはswitch文から抜ける
    • 実行は次のcaseに続かないので、caseの最後で明示的にbreakしなくてよい

よく使う演算子の紹介

  • 代入:=
  • 算術演算子+ - * / %
    • だいたいいつも通りの使い方が出来る
    • 余り%は小数でも計算できる
  • インクリメント/デクリメント:++ --
    • 前置も後置もできる
    • 小数にも使える
  • 複合代入演算子+=みたいなやつ色々
  • 比較演算子== != > < >= <=
  • 範囲演算子.. ...
    • 1..5 => 1,2,3,4,5
    • 1...5 => 1,2,3,4
  • 論理演算子! && ||

ループ(for、while、do-while)

var sum1 = 0
for i in 0..3 {
    sum1 += i
}
// この上下二つのループは同じこと
var sum2 = 0
for var i = 0; i < 3; ++i {
    sum2 += 1
}

var x = 1
while x < 100 {
    x = x * 2
}

var y = 2
do {
    y = y * 2
} while y < 100
  • forループのインデックスの範囲を作るために..を使える
  • 初期化;条件;インクリメントを明示的に書くことも出来る
  • whileループは、条件が変化するまでコードブロックを繰り返すために使う
  • whileの条件は、ループが少なくとも一回は実行されることを保証するために、最後におくことも出来る

関数の定義と呼び出し - 初級編

func getProfile() -> (name: String, age: Int, size: Double) {
    return ("Steve", 46, 8.9)
}
let profile = getProfile()
println("name: " + profile.name)

func squareSum(numbers: Int...) -> Int { // 二乗和
    var sum = 0
    func addSquare(x:Int) { sum += x * x }
    for number in numbers {
        addSquare(number)
    }
    return sum
}
squareSum(4, 6, 8, 9)
  • 関数から複数の値を返すためにタプルを使う
  • 関数は可変引数を取ることが出来る。可変引数は配列になる
  • 関数は入れ子に出来る(関数中のコードが長いあるいは複雑な場合に利用する)
    • 入れ子になった関数は、外側の関数で宣言された変数にアクセスできる
func greaterThanN(n: Int) -> (Int -> Bool) {
    func gt(x: Int) -> Bool {
        return n < x
    }
    return gt
}

func get1st(#condition: (Int -> Bool), #targets: Int[]) -> Int?{
    for item in targets {
        if condition(item) {
            return item;
        }
    }
    return nil
}

let greaterThan300 = greaterThanN(300)
let squares = [11*11, 12*12, 13*13, 14*14, 15*15, 16*16, 17*17, 18*18, 19*19]
get1st(condition: greaterThan300, targets: squares)
  • 関数は、戻り値として関数を返すことが出来る
  • 関数は引数として関数を取ることが出来る
    • 関数をとるパラメーターの型には(引数の型 -> 戻り値の型)を指定する

クロージャ

  • クロージャーは、一連の処理の塊をオブジェクトとして扱えるようにしたものである
  • 他の言語では、関数ポインターとかラムダとかと似たようなものである
var numbers = [4, 6, 8, 9]
numbers.map({
    (x: Int) -> Int in
    return x * x
    })

numbers.map({ number in 3 * number })

sort([1, 5, 3, 12, 2]) { $0 > $1 }
  • 名前なしクロージャーは、コードを{}で囲うことで書ける
  • 戻り値と本体を分けるためにinを使う
  • クロージャーを簡潔に書くための方法
    • クロージャーの型が既知の場合(委譲のコールバックなど)、パラメーターの型や戻り値の型を省略できる
    • 1文のクロージャーは、暗黙にその一文の値を返す
    • 名前ではなく番号で引数を利用できる
    • 最後の引数として渡すクロージャーは括弧の直後にも置ける

標準ライブラリを使いこなす

Swift標準ライブラリリファレンス(Swift Standard Library Reference)
https://developer.apple.com/library/prerelease/iOS/documentation/General/Reference/SwiftStandardLibraryReference/index.html

今のところSwiftのライブラリとしては下記のものがあり、まだ少ないですが、これから充実していく予感がします

  • 型:String、Array、Dictionary、数値型
  • プロトコル:Equatable、Comparable、Printable
  • Free Function:Printing(printとprintln)、Algorithm(sort)


プログラミング言語Swift日本語チュートリアル ~ 後編(Apple公式ドキュメントSwift Tour±α) - こんにゃくマガジンにつづく

後編の内容は、SwiftでのiOSアプリ開発はじめの一歩、クラス、列挙、構造体、ジェネリクス、簡単なネットワークライブラリの使い方となっています。

編集後記

今までネット上の技術ドキュメントに関しては完全なROMだったのですが、
こうして初めて自分で書いてみてなかなか大変な作業だなぁと思いました。
今まで参考にさせて頂いたネット上のドキュメントの執筆者の方々に
この場を借りてお礼を申し上げたいと思います。
ありがとうございました。