June 26, 2016

Swift3.0時代のautoreleasepoolは素晴らしい

Categories: 技術 | Tags: #Swift #Swift3.0 #tips


Swift3.0でautoreleasepoolが強化されたようなので。

はじめに

Swift3.0-preview1時点でのお話となります。

Swift3時代のautoreleasepool

Swift3時代のautoreleasepoolでは、いままでできなかった2つのことが可能になります。

  • 値を返却することができる
  • エラーハンドリングができる

それぞれ順に見ていきます

その前に

autoreleasepoolは以下のように宣言されています。

public func autoreleasepool<Result>(_ body: @noescape () throws -> Result) rethrows -> Result

Generics@noescapethrows,rethrows が使われています。

ちなみに、Swift2時代までは、

public func autoreleasepool(@noescape code: () -> Void)

でした。@noescapeしか目立った特徴がなかったです。

値を返却することができる

今までは、autoreleasepool内で何か操作をして値が欲しい場合には、外にvarで変数を用意して、代入する必要がありました。

var hoge: String?
autoreleasepool {
    // do something
    hoge = "hoge"
}

print(hoge) // => Optional("hoge")

これが、Swift3になると…

var hoge: String = autoreleasepool {
    // do something
    return "hoge"
}

print(hoge) // => "hoge"

と、 スッキリ 書くことができます。
Generics による型推論が働くので、

var hoge = autoreleasepool {
    // do something
    return "hoge"
}

と、変数の型を省略することもできます。

エラーハンドリングができる

個人的にはこちらの方が嬉しかったです。
これができなくて、Swift2時代では自前でautoreleasepoolをオーバーロードして用意していました。

さらに、rethows が付いているため、 closure 内でエラーハンドリングがなければ、autoreleasepoolの外側で一々エラーハンドリングをする必要がなく、通常通り使えることも特徴です。

// 画像を指定したfileURLに保存する

enum CustomError: ErrorProtocol {
    case convertFailed
}

func saveToLocal(_ image: UIImage?, url: URL) throws {
    try autoreleasepool {

        guard let image = image, data = UIImagePNGRepresentation(image) else {
            throw CustomError.convertFailed
        }

        try data.write(to: url, options: .dataWritingAtomic)
    }
}

// ...

do {
    try saveToLocal(image, url: fileURL)
} catch let error {
    print(error)
}

メモリ消費を抑えるためにautoreleasepoolを使って、その内部で例外があれば throw して早めに抜けたい時に便利になりますね。
ちなみに、僕が作っているライブラリでもこれを活用しています。

さいごに

是非、パワーアップしたautoreleasepoolを使ってあげてください!


written by sgr-ksmt