仕様変更【 Swift1.2 / Xcode6.3】まとめ


#はじめに
以前、アプリ開発をしている最中に、
Xcodeを 6.2 -> 6.3
Swiftを 1.1 -> 1.2
にバージョンアップしました。

それに伴い、
エラーが大量発生してしまいましたが、
Xcodeの補完機能（エラーが起きたときにたまに出る**赤色の◯マーク**）
を使用したため、
当時は無事ビルドさせることができました。

しかし、
それだと分かった気持ちで開発していると感じたため、
今回主な変更箇所を調べてまとめてみました。

#変更箇所　Swift
##1. キャストの仕様変更
・新しく**as!**演算子が出来たため、
**as**は**as!**または**as?**で記述しなければなりません。
>実行時に失敗する可能性のあるキャストはas!という新しい演算子をつける

・今まで**as**と記述していた箇所は**as!**に変更すればエラーが消えます。
→[もっと詳しく](http://blog.andgenie.jp/articles/803)

メモ：
・[ダウンキャストとは](http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000107.html)
・[Optional型とは](http://qiita.com/cotrpepe/items/518c4476ca957a42f5f1)

##2. NSStringをStringで扱う場合はキャストしなければならない
>なんだかんだいってSwiftもObjective-Cに頼らないネイティブSwiftとしてのメインストリームを歩んでいきたいわけです

**NSStringの変数**を**Stringの変数**に代入する場合は**as String**でキャスト(型変換)する必要があります。
**Stringの変数**を**NSStringの変数**に代入する場合はキャスト(型変換)する必要はありません。

例)

```.swift
var nsstr:NSString = "文字列"
var str:String = nsstr
nsstr = str
```
↓　**as String**を追加する

```.swift
var nsstr:NSString = "文字列"
var str:String = nsstr as String
nsstr = str
```

メモ：
[NSStringとStringの違い](http://swift-salaryman.com/nsstring.php)

##3. 定数 letの強化
###3.1 条件分岐によりletを初期化することができる
**定数 let**は、
生成時に直接初期化しなくても良いことになりました。

これまで、
条件分岐によって初期化させたい場合は、
変数 **var**を使用してきました。
その後その変数の中身を変更しない場合でも、
変数 **var**を使用することしか出来ませんでした。
**定数 let**の方が適しているにもかかわらず.....

しかし、
Swift1.2では条件によって**定数 let**を初期化させることが出来るようになりました。


例)

```.swift
//以前の書き方
var y:Int = 2
var x:Int = 0
if y == 3 {
    x = 4
} else {
    x = 6
}
```
↓

```.swift
// Swift 1.2
var y:Int=2
let x:Int
if y == 3 {
    x = 4
} else {
    x = 6
}
```

###3.2 if let構文
・１つの**if let文**で複数の宣言ができるようになりました。
・これまでのように**if let文**を入れ子にする書き方もできます。

これでネストの蟻地獄を回避できます！

例) 入れ子にする書き方と複数宣言するやり方です。
**if let文** を複数宣言すると以下のようにシンプルに書くことができます。

```.swift
//swift1.1までのコード (if let文を入れ子にする書き方)
let condition = true
let id: Int? = 1
let value: Int? = 100
let cost: Int? = 300
if condition {
    if let a = id {
        if let b = value {
            if let c = cost {
                if b < c {
                    println(a)
                    println(b + c)
                }
            }
        }
    }
}
```
↓

```.swift
//swift1.2で書けるようになったコード (if let文を複数宣言する書き方)
let condition1 = true
let id:Int? = 1
let value: Int? = 100
let cost: Int? = 300
if condition1,
    let a = id,
    let b = value,
    let c = cost
    where value < cost {
        println(a)
        println(b + c)
}
```



メモ：
[オプショナルの説明](http://tea-leaves.jp/swift/content/%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB%E5%9E%8B)

###3.3 インスタンスの定数への代入は1度だけ
インスタンスの**定数 let**への代入は初期化を含めて1度しかできません。
>1.2からは、**let定数**をイニシャライズで初期化する場合は、定義する際に初期値を設定することが出来なくなりました。

メモ：
[クラスやインスタンスなどの説明](http://tea-leaves.jp/swift/content/%E3%82%AF%E3%83%A9%E3%82%B9)

##4. 新たなネイティブのSetデータ構造
>**CollectionType**に**Array**や**Dictionary**などに加えて**Set**が追加されました。
**Set**は、*値の重複を許さない順序なしコレクション*です。
**Objective-C**の**NSSet**の橋渡しをし、
配列やディクショナリと同じように値に意味を与えます。
そして、**touchesBegan** や **touchesMoved**などのタッチイベント系の引き数の型が、
**Setデータ型**に変わりました。
**Objective-C**の**NSSet**の橋渡しをし、
配列やディクショナリと同じように値に意味を与えます。

例) **NSSet** を **Set< NSObject >** に変更する

```.swift
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
```
↓

```.swift
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
```

##5. staticが使えるようになった
>Swift 1.2から**class**にも**static**な関数やプロパティを持てるようになりました。
これまでもclass funcがありましたが、
**static func**は**class**かつ**final**という意味になります。
また**static let**で宣言した定数は、
最初にアクセスされた時点で評価されるという特徴を持ちます。


```.swift
class StaticPropertiesAndMethods {
    static func printDate() {
        println(date)
    }
    static let date = NSDate()
}

StaticPropertiesAndMethods.printDate() // => "2015-04-10 07:01:00 +0000"
```


[Swift でシングルトン (Swift 1.2版)](http://qiita.com/1024jp/items/4ae93e5e2b3972d679af)

##6. countElements()の廃止
>Swift1.2では、文字数を数えるのにcountElements()ではなくcount()を使います。
ちなみに、1.1でもcount()という関数があり、countElements()と同じであると定義されています。

メモ：
[Swift1.2の関数一覧](http://qiita.com/tottokotkd/items/8a014145a337ee10ba8e)


#Xcode 6.3　について
Xcode6.3から、
古いSwiftのソースコードをSwift1.2仕様にコンバートしてくれる機能がついています。
コンバートとは、修正のプロセスを自動化してくれる移行ツールです。

>1.0と1.1でさほど変更点はありませんでしたが、
1.2では記述が変わったものが幾らかあり、
そのままではコンパイルすることが出来ない可能性が高いです。
そのようなことからXcode6.3では、
古いSwiftのソースコードをSwift1.2仕様にコンバートしてくれる機能がついています。

>【やり方】
メニューの **[Edit]** > **[Convert]** > **[To Latest Swift Syntax...]**で
表示される画面で**[Next]**を押すと、ターゲットの一覧が表示されるので、
**アプリのターゲットのみチェック**をし、コンバートを行います。
コンバートする箇所の検索が終わると一覧で表示されるので、
内容を確認し**[Save]**でコンバート完了です。

#おわりに
以上、【Xcode 6.3 / Swift 1.2】仕様変更について
まとめてみました。

今年の秋頃に、
Swiftがオープンソース化され、
Swift2もリリースされるので楽しみです！

#参考サイト
・Xcode 6.3/Swift 1.2に関する補足情報,マイナビ
URL: https://book.mynavi.jp/support/pc/5353/Xcode63_support/index.html
・[Swift] Xcode6.3に上げたらビルドが通らなかった話
URL: http://www.dorapro.co.jp/engineerblog/?p=688
・Swift1.2のアップデートを備忘録的にまとめる - コンパイルエラー祭りからの脱出 qiita
URL: http://qiita.com/ori_ika/items/d723103b7baa3e22d4a4
・Swift 1.2 で個人的に気になったところまとめ
URL: http://qiita.com/karly/items/3e9c4387f60bfea8424d
・Swift 1.2 and Xcode 6.3 beta
URL: https://developer.apple.com/swift/blog/?id=22
・Xcode6.3アップデートすると必ずやってくるSwift1.2のエラー対処のいくつか
URL: http://qiita.com/osamu1203/items/09ab7ba89b2101a855f7
・Swift 1.2 cockscomb on hatena blog
URL: http://cockscomb.hatenablog.com/entry/2015/04/30/095612