note8月

Swiftをおさらい

今回はプログラミングに不可欠なSwift言語のキホンをおさらいします。
今年6月のWWDCで発表され次期OSで登場するとされる SwiftUI に対応するためにも、この時期に現在の Swift 言語をきっちり押さえておきましょう!

毎月札幌でiOSアプリ作りをアシストするセミナーをやっています。1時間にわたるセミナーの全内容を、物理的に参加できない方のためにnote上で公開します。ぜひアプリ作りにチャレンジしてください。

おしらせ
iOSアプリ作りをアシストするセミナーは今後も月一回のペースで続ける予定です。
詳細は connpass.com の 札幌Swiftでご確認ください。そして機会があればぜひ参加してください。
アプリ作りやプログラミング教育に関連する話題は 札幌Swift のfacebookページで発信しています。

・画像クリックで拡大表示できます
・画像を拡大表示中は画像の左右をクリックで画像だけを順に表示できます


プログラミング言語は土台

プログラミング言語の知識はアプリ作りの土台です。
アプリを自在に造るには土台がしっかりすればこそです。
Swiftは比較的新しいプログラミング言語です。
ここでは2019年3月にリリースされた Swift のバージョン5 をおさらいします。

プログラミング言語以外のアプリ作りに必要な知識情報については iOSアプリを作ろう・開発に必要な知識 をご覧ください。

筆者は『Swift5初級ガイド』をAppleのブックストアでリリースしました。
Swift5の変更点の解説ではなく最新のSwift5対応の『Swift言語とiOSプログラミング解説書』です。
サンプルは無料です。

画像1


1 Swiftのバージョン

Swift言語のバージョンはコンパイラ(つまり Xcodeのバージョン)で決まります。
Xcode 10.2 以降(と iPad の Swift Playgrounds 3)は Swiftのバージョンは5.0です。
なお秋にリリース予定の Xcode 11で Swift はバージョン 5.1 になるスケジュールです。

Swift 4.2 とSwift 5.0 には大きな変更はありません。
コードの書き直しもほとんど必要なくそのまま利用可能な場合が多いです。

Swiftはほぼ毎年バージョンが上がってきました。1から2、2から3はかなり大幅な変更がありました。このため次のバージョンではどれだけ変わるかがプログラマの気がかりでした。
大きな変更もSwift4でほぼ落ち着いたようです。(Swift4は二度アップデートがあり4.2になりました)
2019年8月現在、書店に並んでいるSwiftの書籍はバージョン4またはそれ以前の内容です。

Xcode 9で作成したコードを Xcode 10 で実行すると、Swiftバージョン違いによる修正が必要な場合コンパイラエラーで修正方法も表示してくれる場合があります。

プログラミング言語・文法は独学可能
コンピュータの知識がある前提


2 オプショナルはどう使う

Swiftでは Optional 以外の型は必ず初期値を設定しなければならないので、値がないことは考慮する必要はありません。
オプショナルだけが値なしの状態を表すことができる特別な型です。

オプショナル関連で「?」と「!」(疑問符と感嘆符)がたくさん登場します。

もしまだ「?」と「!」に違和感があるなら、Playgroundなどでいろいろ試し十分なれてください。

2-1 値があるか 必ず確認

オプショナルの場合は値なしにそなえたコードを書かなければなりません。

// オプショナルの変数宣言
var x: Int? = 3
var y: Int
if x != nil {    // 値があるかの確認
   y = x! + 4    // アンラップして演算
}

▪︎オプショナルは型の直後に疑問符を書く 値なし または 元の型の値
▪︎オプショナルは計算には使えない
▪︎計算に使う場合はアンラップして元の型にもどす
▪︎アンラップする前に必ず値があることを確認する

アンラップが必要なのは煩雑なので、Swiftではいろいろな便利な書き方が用意されています。
ひとつが次の「オプショナルバインディング」です。if let で値があるかの判断とアンラップを同時に、かつ確実に行います。

// オプショナルバインディング
if let okX = x {
   y = okX + 4
}

オプショナルバインディングは if 文の中だけで使えるアンラップされた定数を定義します。
オプショナルの変数に値がある場合だけ if の中身が実行され明快です。
「!」は登場しませんがアンラップもされています。
次のように書くこともできます。

// 同じ定数名を使うオプショナルバインディングも書ける
if let x = x {
   y = x + 4
}

let 直後の x は if 文の中だけで使える定数で、if 文の前に定義されたオプショナルの変数とは別です。

新しい変数名を考えることは、数が増えるほどやっかいです。オプショナルバインディングの { と } の中でアンラップしていない x を使うこともないので、この書き方で問題ありません。

2-2 値なしならデフォルトを使う

a ?? b の書き方で変数 a がオプショナルです。b は a が値なしの場合に使うデフォルトの値です。

// Nil-Coalescing 演算子 ??
let inputYear = Int("2019")    // 文字列から整数に変換 結果は Int?
let year = inputYear ?? 2001    // 値なしなら 2001 を利用
なお a ?? b は三項演算子を使った次のコードに相当します。
a != nil ? a! : b // a ?? b に相当

2-3 プロパティを参照する

オプショナルは元の型とは別の型です。
たとえば UIView? は UIView とは別の型です。
UIView? 型の定数の frame プロパティを参照しようとするとエラーを表示します。

// オプショナルのままではインスタンスのプロパティにあくせすはできない
let v: UIView? = UIView(frame: CGRect(x: 50, y: 100, width: 300, height: 60))
let box = v.frame   // vはオプショナルなのでこの書き方はエラー 

ほかのプロパティにもアクセスする場合にはアンラップしてしまうのが得策ですが、一度限りの場合は行数が増えてしまいます。
そのためOptional Chaining のしくみが用意されました。
アンラップしてプロパティにアクセスでき、v が値なしの場合はエラー発生ではなく値なしを返します。
値なしを返す場合があるので結果はオプショナルです。

// オプショナルチェイン
let box = v?.frame   // 結果はオプショナルになる

この場合 box の型は CGRect? となります。
オプショナルチェインはプロパティだけでなく、メソッドの実行もできます。

2-4 値なしを扱うわけ

わざわざオプショナルとして値なしを扱えるようにしている理由はいくつかありますが、明快なのは文字列から数値に変換するイニシャライザです。

// Int型のイニシャライザのひとつ。文字列から変換する。
init?(_ description: String)

このイニシャライザは"2020"などの文字列をInt型の数値に変換します。
数字を含まないなどInt型の数値に変換できない場合に値なしを返します。
このイニシャライザが変換できない場合はゼロを返すとしても、文字列が "0" の場合と区別することができません。
これは『変換できない場合を 999999 にする』と変更しても根本的な解決にはなりません。
Swiftでは変換できない場合にそなえオプショナルを使います。変換できない場合は値がない状態になり、正常に変換できた場合と明確に区別します。

2-5 感嘆符のオプショナル

アプリでは次のようなコードが使われます。

// マップビューのアウトレット
@IBOutlet weak var mapView: MKMapView!

@IBOutlet と weak はそれぞれ Swift の予約語です。
ここでは最後の感嘆符に注目してください。
MKMapView! もオプショナルです。
型の直後に感嘆符をつけると Implicitly Unwrapped Optional(インプリシットリ・アンラップド・オプショナル)を意味します。

Implicitly Unwrapped Optional(IUO と書く場合もあります)の「Implicitly」は『暗黙の』の意味です。この型のオプショナルの変数は感嘆符を付けてアンラップする必要がありません。
しかし値なしで利用すると実行時エラーが発生します。

アプリでストーリーボードのアウトレットは自動的にこの Implicitly Unwrapped Optional になります。
ストーリーボードの仕組みではビューコントローラーのインスタンスが利用可能な状態なら、アウトレットも実態と接続済で利用可能です。
正しく接続されたアウトレットは原理的に値なしではないため Implicitly Unwrapped Optional が使われます。


3 クラスと継承

Swift では class と struct は似ていますが、class だけが「継承」できます。

『継承(Inheritance)』は元になる class のプロパティ定義やメソッド定義を引き継ぐこ とです。
元になる class をスーパークラス(superclass)、継承している class をサブクラス (subclass)と呼びます。
歴史的に Objective-C を使った Cocoa と Cocoa Touch は class で構築されています。
そのため UIKit などのフレームワークは class とその継承機能を使い実装されています。
このため iOS や macOS プログラミングでは継承の理解が不可欠です。

「継承」などオブジェクト指向プログラミングの用語は繰り返し確認し、しっかり理解してください。

3-1 self と super

継承した場合にスーパークラスのプロパティやメソッドと自分自身のプロパティやメソッドを区別す るには super を使います。一方 self は継承していなくても使う場合があります。
自分自身のプロパティなら self.プロパティ名 スーパークラスのプロパティなら super.プロパティ 名 とします。self と super をインスタンスの変数名の代わりに書くわけです。

3-1-1 self
メソッドを実行しているオブジェクト(インスタンス)をあらわします。 class だけでなくほかの型でも使います。

3-1-2 super
スーパークラスのオブジェクト(インスタンス)をあらわします。継承の連鎖をたどってスーパーク ラスに定義されたメソッドやプロパティを呼び出すことができます。

3-2 継承関係とインターフェースビルダー

UIKit フレームワークの UIControl は UIView を継承しています。
これは UIControl のインスタンスは UIView のプロパティを持っていることを意味します。
UISegmentedControl は UIControl を継承しています。

// UISegmentedControl の宣言
class UISegmentedControl : UIControl

UISegmentedControl のインスタンスは UIControl のプロパティも UIView のプロパティも持っていることを意味します。

継承関係は大規模なフレームワークを構築しやすく利用しやすくしていてます。
たとえばインターフェースビルダーのアトリビュートインスペクタは継承関係でプロパティの設定画面がレイアウトされています。

一番下が UIView のプルパティの設定、その上が UIControl、一番上が UISegmentedControl のプロパティの設定です。

画像2

3-3 カスタマイズと継承

iOS(つまり Cocoa touch)では、独自のUIを作るための UIView などを継承することはあまり多くはありません。
文字表示には UILabel 、アイコンなどには UIImageView を組み合わせるなどして目的の画面を構成するのが基本です。

UILabel や UIImageView、それにコントロール類もたくさんの表示オプションがあり、標準機能でかなり見た目のカスタマイズが可能です。

メーター表示のような組み合わせで実現できない場合にだけ UIView を継承し独自の描画処理を実装します。
独自のビューを作った場合はアクセシビリティ対応などの対応も必要な場合があります。次のiOSではダークモード対応も必要になります。

一方 UIViewController のように常に継承して利用するクラスもあります。


4 型とプロトコル

プロトコルはプロパティやメソッドで性質や機能が使えることを保証するしくみです。
むずかしく聞こえますが実際には、プロトコルはプロパティやメソッドの名称と型だけを定めているだけです。
プロパティで値や状態を確認し、特定の機能を実行するためにメソッドを呼び出すためです。

続きをみるには

残り 6,343字
この記事のみ ¥ 500

今後も記事を増やすつもりです。 サポートしていただけると大変はげみになります。