Swift 実践入門 を読んだ

Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

全体感想

良い本だった、書名になっているが初心者向けではなく実践入門なので、実践的な内容が多くためになる。
だいたい 16 時間くらいで読みおわった。

普段ゆるふわで書いているとクロージャジェネリクスなど使いこなせていないし、非同期処理なども注意がおそろかになりがちだし、循環参照とかも起きてしまう。
そこらへんちゃんと理解してちゃんと書いていこうという内容であるし、この本を読みながら既存のアプリをリファクタリングしていきたい。

読み終わったら終わりな本ではなくて、手元に置いておいて Swift 書きながら読み返して体に染み込ませていくのがいいのかなと思いました。

石川さんから『Swift 実践入門』を頂いたので、見所などを綴ってみました。 にまともな書評がある。

以下メモ

1章 Swift はどのような言語か

ざっくり Swift こんな言語だよ〜って説明。
静的型付けで Optional 良いよねとかそんな話。
OSS にもなってるよ、コマンドラインとかからでも実行できるよ〜みたいな内容。

2章 変数、定数と基本的な型

変数とか定数、基本的な型(String, Int, Optional など…)の話。
強制アンラップはやべーよなとか、キャストとかも書いてある、ほとんど知ってたけど Swift 書くなら一度読んでおいた方が良い内容。

メモ

  • 定数は宣言時に値を代入しなくても、宣言した後に1度代入されるように書かれていれば問題ない。
  • String の n 文字目を取得するのは characters 型の offetBy を使う、ここら辺は面倒だ。
  • command + control + ? (英字keyの場合は command + control + shift + / ) で型情報見れる。
    • 知らなかった、便利だ。今まで画面右の Quick Help で見てた。
    • 長いのでエイリアス当てておきたい

3章 制御構文

if, switch, guard などのはなし、深く実践的な内容が書かれている。

メモ

  • if case 1...10 = value みたいに書く。この書き方いつも忘れる。
  • switch casewhere はあまり使ってない、というか存在を忘れていたので今後使っていこう。
  • switch の default を書いちゃうと今後増えた時に全部 default 入っちゃってよくないから default は極力書かないようにしよう。
  • for-case in という書きかた普通に知らなかった、便利だ。
  • while は嫌いだから俺は使わない
  • defer は遅延処理
  • enum はもっとうまく使わないとなあ

4章 関数とクロージャ

関数は他の言語と大体同じ。
クロージャは使いこなせておらず知らいことが多い、めっちゃ便利だがそれなりに難しく、後3回くらい読み直したい。

メモ

  • インアウト引数はあまり使い慣れない
    • 関数先で渡した引数が更新されるのわかりにくくない?
  • クロージャは1行の時だけ return 省略できる
  • キャプチャ
    • クロージャ内部の変数を保持することができる。
    • 用途によって色々使えそう。
  • 関数の引数にクロージャ渡すとかめっちゃ便利そうだが複雑になって脳内メモリ足らなくなる

5章 型の構成要素

class, struct, enum で利用出来るプロパティやメソッドの説明。
今まで雰囲気で Swift 書いてきた人間はこの章で死ぬ。

メモ

  • プロパティオブザーバ
    • willSet, didSet あたりあまり使いこなせてない
  • 失敗可能イニシャライザ使いこなせたら強そう
  • subscript 全く使いこなせてない
    • コレクション要素にアクセスできるやつ、 array[0] の [0] の所とか
  • UIAlertController の initializer の所良い、真似しよう。

6章 型の種類

class, struct, enum の説明。
class は参照型、struct は値型で、参照型は意図せぬ値の変更などが起きうるのでなるべく値型を使い、参照の共有が必要な時だけ参照型を使おう。

メモ

  • クラスは参照型で継承が可能、多重継承は出来ない
    • final つければ継承やオーバーライドできなくなる
  • クラスメソッドとスタティックメソッドの違いはオレバーライドできるかできないか
  • enum に値を持たせるのを連想値という

7章 プロトコル

他の言語でいうインターフェースに近い。
100回読みたい。

メモ

  • associatedtype つかえばいま開発中のアプリのやばいところ綺麗に書けそう
  • プロトコルエクステンションにwhereで型制約つけると、その型の時だけ有効になるエクステンション作れる
  • Equatable で URL の一致書こう

8章 ジェネリクス

100回読みたい。

メモ

  • ジェネリック型に具体的な型を与えることを特殊化という。
    • Optional に String とか渡すのもそう。
  • ジェネリクス + 型安全で最高のプログラミング

9章 モジュール

配布可能なプログラム形式(import するやつ)、フレームワークとかを作ろうって話。
普通にプログラム書いてる分には Framework 作ることはないかなと思う。

メモ

  • ドキュメントコメント
    • // や / / は普通のコメント
    • /// や /* / はドキュメントコメント
      • ドキュメントコメントでは Markdown が書ける。

10章 型の設計指針

クラスより構造体を使うべき。
ただしクラスの方が向いている処理もあるので、状況を見て判断すること。

メモ

  • Array や Dictionary はサイズがでかいかもしれないから、それをコピーする時はコピーオンライトって仕組みがあって、必要になるまでコピーされないようになっている。
  • クラスは、参照の共有やインスタンスのライフサイクルに合致した場合などに有用なので、そういう時に使うこと。
  • クラスの継承よりも protocon-extension に優位性があるので、なるべく protocol-extension-struct を使うこと。
  • protocol-extension ではストアドプロパティの保持ができないため、そういう時は class を使う。

11章 イベント通知

UI のタップとかのイベントをどう取り扱うか。 デリゲート、クロージャ、オブザーバパターンなどある。

循環参照について書かれている、100回読みたい。

メモ

  • ボタンタップとかの命名は didSelect などにするのが良さそう
  • delegate は weak にして弱参照にすること
  • クロージャのキャプチャリストを使うときは weak や unowned をつけ弱参照としないと循環参照おきる
    • weak はアクセス時に nil でも死なないが unowned だと実行時エラー起きる
  • self を使うと循環参照する -> 今作っているアプリのあそこ循環参照してる気がする
  • typealias でクロージャの型を作れる

12章 非同期処理

マルチスレッドのはなし。
スレッドを使うにはGCD、OperationQueue、 Thread のどれかを使う。
Thread を使うケースは稀で、簡単な非同期は GCD、複雑な非同期は OperationQueue を使うのが良さそう。

めちゃくちゃためになるというか、真面目に考えないといいアプリにならないがなかなか難しい。
スレッド書くときは読みながら書きたい。

メモ

  • GCD は CPU の負荷などを見ていい感じにスレッド使ってくれる。
    • この手法をスレッドプールという。
    • GCD はシンプルな非同期処理の実現に向いている
      • サブスレッドで実行しその結果をメインスレッドで表示したいとか
      • タスクのキャンセルとかは向いていない
  • Operation, OperatioQueue クラス
    • 内容がだいぶ複雑で頭に入ってこない
  • Thread クラス
    • 継承してクラスそのものを thread にできる

13章 エラー処理

エラーハンドリング。
Optional, Result<T, Error>, do-catch, try, fatalError, アサーションなどの使い方や使い分けなど。

最後にどういういう時にどのエラーを使うべきかという流れが書いてあって便利。

メモ

  • Result<T,Error> はエラーのパターンを判別しハンドリングしたい時に使う
  • try! は危険のように思えるが、失敗したらしゃーないって意図がある
  • do-defer を使うと失敗した時に必ずずっこうしたい処理が書けて良い。
  • do-catch はエラーが起きたかというので取れるので、 Result よりも幅が広く、ネストしたエラーも do-catch であればネストせず行ける。
  • do-catch は エラー処理を強制させる
  • fatalError は想定されていないケースに使う。
    • fatalError が呼ばれることこそが問題だからアプリを落とすという判断
    • fatalError は Never 型を返す。
      • Never 型は空ではなく、そこでプログラムの実行をやめるという意味で何も変えさない
  • アサーション
    • これが有効なのはデバッグ時のみで、リリース時には影響しない

14章 実践的な Swift アプリケーション

API Client を作っていく。
APIKit を作っていく感じ。
Protocol + Extension で抽象的なプログラムを書くの楽しい。

全部写経した。
starhoshi/GitHubSearchRepository: Swift 実践入門

15章 Swift から Objective-C を利用する

Objective-C は実績のある言語だから、過去に書かれた ObjC を Swift で書き直していくにはどうすべきか?みたいな話。
Swift から ObjC の参照の仕方や、 ObjC もちゃんと書いてないと Swift から利用するのはむしろ逆に辛いかもしれないので、 ObjC もちゃんと書こうという話がされてる。

そもそも ObjC 全然詳しくないので勉強にはなるけど、正直 ObjC に努力値振る暇あったら Swift の知見深めたいところではある。

メモ

  • Swift から ObjC を使うときは Bridging-Header を使う
    • Swift 1 のときはライブラリ使うために必要だったな :relaxed:
  • ObjC のランタイムを使うと動的にメソッドの入れ替えなどが可能になるらしい
  • Swift から ObjC を使うにしても、漫然と書かれた ObjC は危険がたくさんなので、 ObjC も気をつけて書いた方が良い
    • ライトウェイトジェネリクス, nullableなど使っていこう
    • id 型はやめろ
  • ObjC から Swift も利用できるけど、制限が多いのでメリットはあまりない