概要
以下の書籍を読み進めた際の読書メモです。
所要時間は約15時間でした。
超詳細に示された手順を辿りながら、アプリ開発の基本的な流れを分かりやすく学べました。
主要なコンポーネントの使い方からWebAPIを使ったデータ取得まで、サンプルアプリを作りながら学べるので、1冊やるだけでもちょっとしたアプリなら作れるようになると思いました。
書籍概要
- 書籍名:たった2日でマスターするiPhoneアプリ開発集中講座
- 著者 :藤治仁・小林加奈子・小林由憲
- 発刊日:2019/10/23
- 頁数 :424ページ
読書ノート
開発方法・ビルド
-
主な開発の流れ
- Xcode上にパーツを配置し画面レイアウトを作る
- パーツとコードを接続(connect)し、動作を記述する
- シミュレータや実機で動作を確認する
-
実機で動作確認する場合、Xcodeに登録されたApple IDと、実機に設定されているApple IDが同じである必要がある
- Xcodeには複数のApple IDを登録できるが、その中に実機と同じApple IDがあれば良い
- ビルド時に選択するTeamは、実機と異なるApple IDのものでも問題ない
-
プロジェクト設定でTeamを選択時に「Failed to register bundle identifier.」エラーが出た場合の対応
- 「Bundle Indentifier」の値を変更すれば良い(末尾に日時を入れる等)
レイアウト
- AutoLayoutを使うと画面パーツの配置やレイアウトを整えることができる
- 色々な端末の画面サイズに対応するためには重要な機能
IBOutlet・IBAction
-
IBOutletについて
-
@IBOutlet weak var answerImageView: UIImageView!
-
IBOutlet修飾子
Interface Builderにあるパーツとコードを連結することを示すキーワード -
weak var answerImageView
:変数の定義(answerImageView
が変数名) -
: UIImageView
:クラス(型)の指定(変数名:データ型
) - このコードで、UIパーツのImageViewを、コード上でanswerImageViewという名前で参照・設定できるようになる
-
-
-
IBActionについて
-
@IBAction func shuffleAction(_ sender: Any) { ... }
- 紐付いたパーツがユーザによって何かしら操作された際、実行するプログラムを連結するキーワード
-
変数・定数
-
let
で定義した値は一度値を設定したら変更できない(=定数)- 変数は
var
で定義する - 上手く使い分けることでコードの安全性が向上する
- 変数は
アクセス修飾子
- Swiftのアクセス修飾子
- public:どこからでもアクセス可能
- internal:同じモジュール内であればアクセス可能
- fileprivate:ファイル内でのみアクセス可能
- private:現在の定義の中でのみアクセス可能
Storyboard・パーツ
-
パーツとコードの関連付けを解除する場合、コードを削除するだけではダメ
- StoryboardのView Controllerから解除する必要がある
- 再度関連付けする場合、コード横の白丸を対象パーツにD&Dする
- StoryboardのView Controllerから解除する必要がある
-
Storyboard上にパーツを配置する際、コピペはしないようにする
- 特に、アクションを設定するボタン等をコピペした場合、コードとの関連付けが上手くいかなくなる場合がある
値の参照渡し
- メソッド呼び出し時、引数の先頭に
&
を付けると参照渡しが可能- 引数に指定した変数やインスタンスそのもの(同アドレス)にメソッド内で変更を加えたい場合は参照渡しを使う
- 変数のコピーではなく変数のアドレス情報を渡すので、メソッド内での変更が元の値に影響する
- 先頭に何も付けなければ値渡しになる
- コピーを渡すだけなのでコピー先で変更があっても元の値には影響がない
- 引数に指定した変数やインスタンスそのもの(同アドレス)にメソッド内で変更を加えたい場合は参照渡しを使う
例外処理
- 例外処理
- 例外処理は
do-catch
ブロックで行う - メソッド呼び出しの前に
try
文を記述するsample = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil)
- 例外処理は
Delegate・DataSource
-
Delegate機能を使うと、特定の操作(文字入力等)が完了したタイミングでプログラムを動作させることができる
- あるクラスで行いたい処理の一部を他のクラスに任せたり、任せた処理を指定したクラスに通知したりする仕組み
- Delegateが行われる時に登場するものは大きく3つ
- 処理を依頼するクラス(例:
inputeText.delegate = self
)- 処理結果の通知先を自分自身(ViewController)とし、TextFieldクラスから作ったinputTextにdelegateを設定
- 依頼する・依頼されるクラスを取り持つプロトコル(例:
UITextFieldDelegate
)- return操作が行われたら、設定された通知先に結果を通知するよう、UITextFieldクラスに依頼する
- 処理を依頼されるクラス(例:
UITextField
)- UITextFieldDelegateから通知を受けたら、通知先(ViewControllerのtextFieldShouldReturn)に結果を通知する
- 通知先はプロトコルが処理してくれるので、このクラスは通知先を知らなくても良い(汎用的に利用できる)
- 処理を依頼するクラス(例:
- ViewControllerの宣言に記述を追加する
- 例:
class ViewController: UIViewController, UITextFieldDelegate { ... }
- 例:
-
TextFieldのDelegate
-
textFieldShouldReturn() { ... }
:Return操作(「検索」ボタンを押す等)が行われたら実行されるメソッド- メソッド名はあらかじめ決まっている
-
-
DataSource
- UIパーツとコード間でデータのやり取りを行うために定義する
オプショナル・アンラップ・オプショナルチェイニング
-
オプショナル
- 値がない状態を許すデータ型のこと
- 変数宣言時のクラス名の後に
?
または!
を指定する(一般的なオプショナル型は?
を付ける)- これらが無い宣言は、「非オプショナル型」になる(値がない状態を許さない)
-
アンラップ
-
if let ...
を使うと、値がある場合のみif文内が実行されるとともに、変数に値が格納される- オプショナル型の変数やメソッドを安全に取り扱う手法のこと
- 例:
if let searchKey = textField.text { print(searchKey) }
- 値があれば、
print(searchKey)
が実行されるとともに、searchKey
に値が格納される
- 値があれば、
- アンラップ処理は入れ子にして使うことも出来る
-
-
オプショナルチェイニング
- アンラップの手法の一つで、値がある場合のみ、続くメソッドが実行される
- 例:
_ = navigationController?.popViewController(animated: true)
-
navigationController
に値が入っている場合のみ、popViewController
が実行される
-
- 例:
- アンラップの手法の一つで、値がある場合のみ、続くメソッドが実行される
-
guard let
を使うとオプショナル変数の値を安全に取り出せる-
if let
は「アンラップできたら」だが、guard let
は「アンラップできないときは」という条件で分岐する- 例:
guard let アンラップ変数 = オプショナル変数 else { オプショナル変数に値がない時の処理 }
- オプショナル変数に値がない時の処理には、
return
などのプログラムが終了するコードのみ記述可能
- オプショナル変数に値がない時の処理には、
- 例:
-
クロージャ
- クロージャ
- 引数などに
{}
でまとめて処理を渡して実行させる方法のこと- 例えば
CLGeocoder.geocodeAddressString()
などに渡して、位置情報取得後の処理を第2引数に書いたりする
- 例えば
- 主な記述方法:
- 引数などに
{ (引数:引数の型) -> (戻り値の型) in
何らかの処理
return 戻り値
}
UserDefaults
- UserDefaults
- UserDefaultsを使うと、アプリで利用する値を保存できる
- 異なる画面間で値をやり取りする時などに使う
- 値はKVで保存され、アプリを停止・再起動しても保存されている(永続的)
- 永続化は定期的に実行されているが、即座に永続化するには
synchronize
を利用する
- 永続化は定期的に実行されているが、即座に永続化するには
- UserDefaultsにアクセスする場合、(必要に応じて)都度UserDefaultsインスタンスを生成してから値を呼び出す
- UserDefaultsを使うと、アプリで利用する値を保存できる
Segue(セグエ)
- Segueを使って画面遷移する際に
prepare
メソッドが実行されるoverride func prepare(for segue: UIStoryboardSegue, sender: Any?) { ... }
画像の取り扱い
- Appleが提供している画像処理フレームワーク「Core Image」を使うと、簡単に画像にフィルタをかけたりできる
音声の取り扱い
- 音を扱うためには「AVFoundation」というフレームワークを読み込む必要がある
マップの取り扱い
-
CLGeocoder
クラスを使うと、緯度経度から住所を検索、またはその逆を行うことができる-
CLGeocoder.geocodeAddressString()
:郵便番号や住所等から様々な情報を取得してplacemarks
に格納する-
placemarks
はCLPlacemarks
クラスのインスタンス
-
-
ラベル(名前付き引数)
- メソッドのラベル(名前付き引数)について
- メソッドのラベルは、メソッドの呼び出し側でより引数を分かりやすくするために使う
- メソッド名から引数の意味が分かるような場合、引数ラベル省略「
_
」を利用して呼び出し側でラベルを省略可能- ラベルを省略した場合は引数名がラベルとして扱われる
- メソッド名から引数の意味が分かるような場合、引数ラベル省略「
- メソッドのラベルは、メソッドの呼び出し側でより引数を分かりやすくするために使う
// ラベルを付与する場合
// 合計値を計算
func calcSum(quantity qt: Int, price pc: Int) -> Int {
// メソッド内ではラベルではなく引数を使う
return qt * pc
}
// メソッド呼び出し(ラベルを使って引数を指定できる)
calcSum(quantity: 2, price: 300)
// ラベルを省略する場合
// デバッグエリアに文字を表示する
func debugMessage(_ message: String) {
print("\(message)")
}
// メソッド呼び出し(引数のラベルを省略できる)
debugMessage("デバッグエリアに表示する文字")
JSON
-
Codable
プロトコルを利用すると、JSONの項目名とコード中の変数名を同じにした場合に、JSON変換時に一括して変数にデータを格納してくれる
ATS
- ATSを有効化すると、HTTPでインターネットに接続できなくなる
- また、HTTPSを使っていても、Appleが推奨するセキュリティ要件を満たしていなければ同様に接続できなくなる
- 無効化すればHTTPやセキュリティ要件を満たさないHTTPSでも接続できるようになる
タプル
- タプルを用いると、複数の値を一つの変数として扱うことができる(KVを一つにまとめカンマで区切る)
- タプルは配列のように値の追加・削除・データの個数変更等はできない
- 例:
(key1:String, key2:String, key3:Int)
その他
-
viewDidLoad
メソッドはアプリ起動時に一度だけ動くようにあらかじめ作られている- この中に書いたコードもアプリ起動時に一度だけ動作する
-
引数のデータ型に
inout
を指定すると、引数として受け取り、かつ戻り値としてその値を返す- return文を書かなくても戻り値を返してくれる
-
Objective-Cで書かれたクラスをSwiftで利用する場合、宣言の先頭に
@objc
を付ける必要がある -
戻り値のあるメソッドを呼び出してかつその戻り値を利用しない場合、「
_
」に代入する- 例:
_ = updateTimer()
(updateTimer()
はInt型の値を返す)
- 例:
-
文字列の中に定数や変数を埋め込む場合、「
\(定数 or 変数)
」と記述する- 例:
label.text = "残り時間:\(remainCount)秒"
- 例:
-
既存のクラスを拡張する場合は「Extension」を用いる