hireLink vol.3
プロとして通用するiOS開発者になろう!
知っておきたい5つのSwift新技術



2015年8月27日 (木) @ 株式会社トライブ
新居雅行 Masayuki Nii
独立系エンジニア, トレーナー, 博士(工学)
nii@msyk.net msyknii msyk_nii

自己紹介:新居雅行(にいまさゆき)

システム開発を自営業者として行う

iOSやOS Xのネイティブアプリケーション
FileMakerのソリューション開発。特にカスタムWeb
データベース絡みのWebアプリケーション
コンサルティング、トレーニングコース開発、トレーナー
博士(工学)、Apple認定トレーナー

iOSとの関わり

2008年、App Store開設時に『郵便番号検索』をリリース
その後、さまざまなiPhone/iPad向けのプロジェクトに参画
2012年よりナガセITスクールのトレーナー、コース開発を担当
技術評論社や自費出版など、iOS開発関連書籍を6冊執筆

Agenda

iOS開発のポイントを「5つ」解説します

  • 画面解像度に依存しない「オートレイアウト」
  • マルチタスク画面を念頭にした「サイズクラス」
  • 画面更新の呪縛を逃れる「オブザーバー」
  • 通信処理を簡単にマルチタスク化する「NSURLSession」
  • 進化した言語の「Swift」

今時のiOS開発の現場

iOSがビジネスになることは証明されている

App Storeを通じた世界への販売
サービスインフラとして確立したスマホ
地味ながらも業務システムへの展開もある

iOSの開発は何で行うか?

Webアプリ vs ネイティブアプリ、あるいはハイブリッド?
ネイティブアプリのニーズが高い市場でもあるiOS(完成度、販売ルート)

ネイティブアプリの開発者としてのスキル

プログラミング言語によるプログラミング

仕様や要求に応じた結果をコードとして生成できる
APIの使い方や癖などを把握し、品質の高いコードを生成できる

チーム開発で発揮できるコミュニケーション能力

iOSの開発初期のころは単独開発が目立ったが、チーム開発も一般的に

市場ニーズを見極める能力

不要なものをリリースしても、誰もダウンロードしない

英語、特にリーディングの能力

最新の開発関連情報を得るには、せめて英語のリーディングは必須

iOS開発の簡単さと複雑さ

簡単になったと言えるところ

ストーリーボードを利用したUI開発
ハードウエアやOS自体の進化による機能アップ

複雑になったと言えるところ

デバイズの解像度がiPhone 6時代に一気に増えた
Split Viewにより、iOSにも「可変解像度」の時代が来た
開発に求められる要求が次第に高度になっている
難しくなったというよりも、市場の要求が高くなった

画面解像度に依存しない
「オートレイアウト」

解像度や回転に追随するためのオートレイアウト

縦横座標に依存したレイアウトの限界

画面ごとにレイアウトを用意する=もはやありえない、連続変化には対応できない
現状にフィットさせるコード=現在も可能だが、開発コストがかかり、新しい解像度への対応ができない
オートサイジングがあるのでは?=ウインドウシステム向けの機能であり、もはや機能的に追いついていない

座標値を決定づける「制約(Constraints)」オブジェクト

属性(高さや幅)に対する値を指定する
位置を、別のオブジェクトや上位ビューの端からの距離で定義
Interface Builderで設定可能

「制約」オブジェクトの例

デモ

  • 画面解像度の変化に対応したオブジェクトの配置
  • 制約を設定する操作とそのコツ

マルチタスク画面を念頭にした
「サイズクラス」

サイズクラスは画面が持つ特性

デバイスやビューコントローラーは「サイズクラス」を持つ

「サイズクラス」という属性(あるいは分類)
縦横軸それぞれについて、Regular/Compact/未定義の3通りの値
プログラム言語での「クラス」ではない!

サイズクラスを持つオブジェクト

デバイス、デバイスのスクリーン
ビューコントローラー

iPadに定義されたサイズクラス

iPhone 6 Plusに定義されたサイズクラス

その他のiPhoneに定義されたサイズクラス

デモ

  • サイズクラスに依存したレイアウト機能
  • プレビューで結果を確認する

ようするにサイズクラスは何なのか?

現状の解像度の指標

機種名を直接言及しない=将来の機種追加への対応
オートレイアウトが前提=追随はこちらの機能、サイズクラスで大まかな動作を定義
2種類で分類できることが本当に正しければ大きな発見かもしれない

UISplitViewControllerはサイズクラスで動作が違う

Landscape iPhone 横方向:Compact→2分割せず
Landscape iPhone 6s、iPad 横方向:Regular→2分割する
Portrait iPhone 横方向:Compact→2分割せず
Portrait iPad 横方向:Regular→2分割するが一方は最初に隠す

画面更新の呪縛を逃れる
「オブザーバー」

実装のアーキテクチャーで複雑な問題を解決

複数のビューコントローラーで顕在化する問題

モデル→コントローラー→ビュー、だけならシンプル
ビューの変化が別のビューの更新が必要になったら?
そういう仕組みをいくつか書くと循環的に動くようになる

オブザーバーのクラスが用意されている

実装の基本は、モデルの値の変化を伝達する仕組みを実装し、更新はモデルに対して行う

MVCパターンの実装

MVCにはいろいろな考えがあるが…

ビューをInterface Builderで作るリソースという考え方

複雑な状況

例えば複数のビューがある

一方のビューの更新で、別のビューの更新が必要

複雑な状況をどう解決するか?

根本的な解決策は「オブザーバーパターン」

Core Dataにおけるオブザーバーの仕組み

NSFetchedResultsController

マネージドコンテキストの階層化とメインスレッド上での監視
モデルが生成し、コントローラーで保持する

通信処理を簡単に
マルチタスク化する
「NSURLSession」

通信処理を簡単にマルチタスク化する「NSURLSession」

通信は「必須」のはずなのだが…

初期からのNSURLConnectionは使いにくい、マルチタスク化しづらい
ASIHTTPRequestというフレームワークがメインになってしまった

簡単にマルチタスクや通信を実現するNSURLSession

受信後の処理は別スレッドでかつクロージャーで定義する
ただし、その中でのUIKitの操作は「メインスレッド」で行う
HTTP認証なし、正しい証明書、プログレス不要なら簡単に実装できる

実装の例

let url = NSURL(string: "http://msyk.net")
let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithURL(url!, completionHandler: {
    (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
            
	let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
	// setup the model with dataString.
	session.finishTasksAndInvalidate()
	
	let mainQueue = NSOperationQueue.mainQueue()
	mainQueue.addOperationWithBlock({
		tableView.reloadData()
	})

})
task.resume()

複雑な処理を必要とする場合

デリゲートメソッドの実装が必要な場合

最近ほとんど使われなくなった自己署名証明書でのSSL通信
HTTPプロトコルによる認証を通す場合
通信途中のプログレス表示をさせたい場合
バックグランドプロセスに通信させる場合

コンフィグレーションのカスタマイズ

特別なプロキシの設定
回線に応じた処理の追加

進化した言語の
Swift

Swiftの特徴

プロパティのさまざまなバリエーション

セッター、ゲッターはもちろん、オブザーバー的な実装、遅延設定

安全なコードを言語レベルでサポート

オプショナル、ARC対応

言語の世界では比較的新しい仕組み

ジェネリック、エクステンション、階層化された定義、タプル、列挙、クラスに近い構造体

その他

スピード、インタプリタ(プレイグランド)
Objective-Cに比べて、普通の言語っぽい記述

オプショナル

値が割り当てられていないことを言語でサポート

オプショナルの問題点と動向

APIの返り値や引数が?や!など、一見すると統一性がない

Xcodeに任せればほぼ補完してくれる
理由はObjective-Cにオプショナルの概念がなかったから。Xcode 7でかなり改善

IBOutletはどうしても!にしないといけないか?問題

いけないわけではないが、Appleの推奨は!
本来は?であるべきでは?
Interface Builderの動作とどう親和性を取るか?今後に期待!

キャストや変換のasやas?に、さらにas!まで加わった!(Ver.1.2)

!は強制変換を失敗する可能性があるという意味

Swfitでのクラスの例

willSet/didSetによりプロパティの更新前後にプログラムを定義

StringやArrayは構造体だった!

Objective-Cはクラス、=により参照が代入される

Swiftは構造体、=により複製された結果を代入

まとめ

現在のiOS開発で必ずキャッチアップしておきたい技術

  • 画面解像度に依存しない「オートレイアウト」
  • マルチタスク画面を念頭にした「サイズクラス」
  • 画面更新の呪縛を逃れる「オブザーバー」
  • 通信処理を簡単にマルチタスク化する「NSURLSession」
  • 進化した言語の「Swift」