デザイナー→Webエンジニア→iOSエンジニア

と渡り歩いた僕なりのSwiftとの向き合い方

と生かす戦略
iOSDC	Reject	Conference	Day2	@	DeNA
2019/09/18
Fumiya	Sakai
自己紹介
・Fumiya	Sakai
・Freelance	iOS	Engineer
アカウント:
・Twitter:	https://twitter.com/fumiyasac

・Facebook:	https://www.facebook.com/fumiya.sakai.37

・Github:	https://github.com/fumiyasac	

・Qiita:	https://qiita.com/fumiyasac@github
発表者:
・Born	on	September	21,	1984
これまでの歩み:
Web	Designer
2008	~	2010
Web	Engineer
2012	~	2016
App	Engineer
2017	~	Now
技術書典7でiOSのUI実装本の続編を頒布します
少しの工夫で実現できるTIPS集 ライブラリ表現の活用集
様々なUIライブラリを利用したサンプル解説の書籍になります 場所は 【あ11C】 です
現在の僕自身のSwiftとの向き合い方について
以前のTry!Swift開催前に登壇した資料にも一度まとめています。
iOSアプリのUI表現の実装手段の模索をアウトプットの中心に据えている
この部分に取り組むことになったきっかけ:
①	自分が一番関心が高い
②	最初一番苦労した部分
デザイナーを若い頃に経験した際
にFlashコンテンツ等インタラク
ションがあるコンテンツ開発に携
わっていた名残もある。
iPhoneアプリ開発を始めた際に一
番試行錯誤した部分であった。
https://www.slideshare.net/fumiyasakai37/iosuiswift
経験職種がバラバラだから一貫性がない?
これまでの知見を捨て去るのではなく、上手に生かした戦略を見出そう
少しでも経験をしていることが思わぬ強みになることだってある
Web	Designer Web	Engineer App	Engineer
それぞれの職種を経験した時の仕事の仕方や進め方・今抱えている事情や背景を理解することにも努める
そうはいっていも、迷走している状態になる瞬間はある😕
デザインにおけるWebとアプリの違いを見極める(1)
Case1.	テキスト表示とハイパーリンクのような動きをアプリで実現する場合
Webであれば頻出ではあるがアプリだとちょっと一手間がかかる事例
個別に指定すると記述量も増える&煩
雑になってしまうことが多い。
⭐ 	コード設計が大事
AttibutedTextを利用する:
表現によってはUILabelやUITextView
だけでシンプルにできない時も。
⭐ 	表示する情報の定義
どのあたりまで柔軟性をもたせるか:
AttibutedStringをより直感的に記載する

SwiftyAttributes:

https://github.com/eddiekaiger/SwiftyAttributes
テキストの取り扱い問題解決のためのアプローチ例(1)
例1.	自前で対応することが困難な場合にはライブラリを活用する
簡単なリンクやハッシュタグ等ある程度のパターンが決まっている場合
App	Engineer
⭐ 	文章中のURLリンク・ハッシュタグ・メンション
UILabelで表示する要素の中に押下可能なエリアを設ける場合: ActiveLabel.swift
https://github.com/optonaut/ActiveLabel.swift
テキストの取り扱い問題解決のためのアプローチ例(2)
例2.	サーバー側と協力することで表示にコンテンツにある程度柔軟性を持たせる
表示データをサーバー側でMarkdown形式で保存させておく
SwiftyMarkdown
https://github.com/SimonFairbairn/SwiftyMarkdown⭐ 	Webサイトとアプリでも表示を合わせやすくする形式
シンプルで編集者等が更新しやすい形式:
Redcarpet
https://github.com/vmg/redcarpet
サーバー側のコンテンツについて
はMarkdown形式を保存・表示。if let url = MediaContents.url, let md = SwiftyMarkdown(url: url) {
md.setFontNameForAllStyles(with: "HiraKakuProN-W3")
md.setFontSizeForAllStyles(with: 13.0)
md.h1.fontName = "HiraKakuProN-W6"
md.h1.fontSize = 18.0
…
markdownTextView.attributedText = md.attributedString()
}
UITextViewを継承したMarkDownTextView型
Webフロント側の表示にRedcarpetを利用する。
App側 Web側
デザインにおけるWebとアプリの違いを見極める(2)
Case2.	パンくずリストのような表現
Webでは当たり前にあるけどアプリだとそうでもない事例
iOSアプリに関しては、一気にRootま
で戻る必要があるケースが少ない。
⭐ 	最初疑問に感じていた部分
アプリだと少ない気がする:
デザイン的な表現だけではなく、戻る
画面遷移時にも配慮が必要になる。
⭐ 	表現や構造の工夫が必要
右側のアロー表現との兼ね合い:
// テキストの属性を設定する
var categoryTitleAttributes = [NSAttributedString.Key : Any]()
categoryTitleAttributes[NSAttributedString.Key.font] = UIFont(
name: AppConstant.CATEGORY_FONT_NAME,
size: AppConstant.CATEGORY_FONT_SIZE
)
// 引数で渡された文字列とフォントから配置するラベルの幅を取得する
let categoryTitleLabelSize = CGSize(
width: .greatestFiniteMagnitude, height: AppConstant.CATEGORY_FONT_HEIGHT
)
let categoryTitleLabelRect = title.boundingRect(
with: categoryTitleLabelSize, options: .usesLineFragmentOrigin,
attributes: categoryTitleAttributes, context: nil)
パンくずリスト型表現のアプローチ例(1)
配置したUILabelを幅	=	表示されるテキストとの長さをする処理がポイント
基本的な方針としてはUICollectionViewやUIScrollView	+	UIStackViewを利用
UIStackView
UIScrollView
Home ▶︎ Contents
テキストが入ります ▶︎
⭐ 	sizeToFit()・sizeThatFits(CGRect)を活用
AttibutedTextの場合はBoundingRectから算出する:
※	この例はパンくずリストへ表示される階層が決まっている場合テキストの長さ+矢印の長さ
1つのボックスの幅を決定するための基本方法:
AutoLayout

幅制約値更新
(Equal	Spacing)
パンくずリスト型表現のアプローチ例(2)
テキストを利用した表現方法についてはあったけどライブラリは少ない…
ライブラリを活用する場合の例やその他の小ネタ集
表現によっては作り方がなかなか悩ましい部分の例
Home Category Design
https://speakerdeck.com/rikusouda/osswoyu-tenakaraiosahuritehankusurisutowoshi-xian-sita
⭐ 	OSSを育てながらiOSアプリでパンくずリストを実現した
https://medium.com/@thenamesjames/swift-enums-toasted-breadcrumbs-46c1caac855a
⭐ 	Swift	Enums:	Toasted	Breadcrumbs
UIBezierPath()	(ベジェ曲線)を利用して矩形を描画する
綺麗な矢印形を表現するために:
デザインにおけるWebとアプリの違いを見極める(3)
Case3.	商品コンテンツのサムネイル画像をタイル上に並べたレイアウト
Webとアプリの両方の場合でもよく見かけるようなUI表現に関する事例
JSでも有名なプラグインがあり、写真
メインのデザインでも見かける。
⭐ 	プラグインもなかなか豊富
Webサイト構築だとよくみる事例:
UICollectionViewLayoutを利用してレ
イアウト構築クラスの作成が必要。
⭐ 	UICollectionViewLayout
写真の縦横比を綺麗に見せる:
Webとアプリ違いに関するちょっとした余談
Github等でリポジトリを探す前にアニメーション表現や名称や探すこともある
これは良さそう!と思った表現をWebからヒントを得る場合もあります
全く同じ表現をするものではあるけれど、Webとアプリでは難易度が異なる場合に注意をする
実はWebでのUI表現ですでに使われているものがあるかを探ってみる:
⭐ 	UITableViewに配置したサムネイル画像をParallax表示させる(Webだと背景画像を動かすケースが多い)
⭐ 	カメラロールに保存されている画像一覧からドラッグ&ドロップで画像を選択(Webのファイルアップロードが元)
⭐ 	ハンバーガメニューとドロワーメニューの表現(Webサイトの表示でもこちらも良く使われている)
…もちろんこの他にも様々な表現があります。
アプリ側とバックエンド側処理を組み合わせる
前述したMasonryスタイルレイアウト調整を実行する場合の事例と生じた問題
UI側の処理と組み合わせてレイアウト調整を行う場合のアプローチ
extension ViewController: UICollectionViewDelegateFlowLayout {
// MEMO: セル1つあたりのサイズを決定する部分
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath:
IndexPath) -> CGSize {
// TODO: セルのサイズを返却するための処理
}
����・・・(省略)・・・
}
縦横比によって画像部分の高さが変化する場合:
セル1個分の構成
●●●●●●●●●●
●●●●●●●●●●
△△△△△△△△△△
△△△△△△△△△…
xxxxxxxx
2行固定
2行固定
1行固定
縦横比

を維持
このメソッドの中で最初は、画像の実サイズを取得して計算し
たがパフォーマンスに影響が出てしまったので断念した。
[
{
"meals": [
{
"id": 1,
"summary": “サマリーが入ります。",
"image_url": “https://s3-ap-northeast-1.amazonaws.com/…”
“image_width”: 480,
“image_width”: 720,
・・・(その他JSONで返される値が続く)・・・
},
アプリ側とバックエンド側処理を組み合わせる
バックエンド側で返すJSONデータの中に画像のサイズ情報を持たせる
UI側の処理と組み合わせてレイアウト調整を行う場合のアプローチ
⭐ 	sizeForItemAtでは最小限の計算で済むようにする
セル表示データのJSONの例:
セル1個分の構成
●●●●●●●●●●
●●●●●●●●●●
△△△△△△△△△△
△△△△△△△△△…
xxxxxxxx
2行固定
2行固定
1行固定
縦横比

を維持
アプリ内の重い計算を回避するため

(もっと良いアプローチがあるかも)
アプリ側とバックエンド側が絡む部分のデバッグ
サーバーサイドからPush通知を送信する処理で起きた事例
両方のことをある程度理解しないと問題の切り分けがしにくい事例
※	はじめは特定の条件下で起こる事例との見立てではあったが届かない原因を切り分けられていなかった。
機能開発時の不具合報告:
②	失敗するケース
① 成功するケース
Firebase	Cloud	Messaging

を利用したプッシュ通知
App側 サーバー側
②	サーバーから送信
①	Firebaseから送信
Google	APIs	Client	Library	for	
PHPを利用している
https://github.com/googleapis/google-
api-php-client
⭐ 	Laravelを利用する例
https://laravelcode.com/post/laravel-56-
google-firebase-notification-in-android
・Firebaseからの直接送信

・定型文をサーバーから送信
・画面遷移先の判定用パラメー

 タをつけると届かなくなった
ちょっと疑われてしまいそう?
アプリ側とバックエンド側が絡む部分のデバッグ
片方だけの知識ではすぐには見抜きにくいところだった。
実は本当に小さなミスによって生じていたことがわかった
FCMに送信するJSONの形式: 原因はキャスト漏れであった(Int → String):
{

 	"message":	{

 	 	“token”:	"(Target	Device	Token)",

 	 	“notification":	{

 	 	 		"title":"タイトルメッセージ",

 	 	 	“body":"タイトル本文テキスト"

 	 		},

 	 		"data"	:	{

 	 	 		"parameter"	:“Example”

 	 		}

 		}

}
https://firebase.google.com/docs/cloud-
messaging/ios/receive?hl=ja
絡み合うケースの調査は大変
アプリ側とバックエンド側が絡む部分の設計
アプリ側だけでは完結できない様な機能を作る場合
お金やセンシティブ情報を扱うアプリで起動時のパスコードロックを忘れた際の機能を考える
https://qiita.com/fumiyasac@github/items/6124f9b272f5ee6ebb40
参考資料: 画面のパスコードロック機能を構築する際における実装例とポイントまとめ
Q.	パスコードロックをユーザーが忘れた際はどうするか?
パスコードを忘れた場合の配慮:
アプリを再インストールさせる方法は
結構ユーザーの印象が良くない?
すでに会員情報をサーバーに保持し
ているのならそれを活用する?
⭐ 	アンインストールはさせない
⭐ 	アプリ内の情報を利用する
アプリ側とバックエンド側が絡む部分の設計
メールに添付されたURLを利用してアプリのパスコードを解除する
APIサーバー側 アプリ側
送られたリクエストから
該当ユーザーへメール送信
パスコード解除用の
メール送信リクエスト
※ 有効期限を短めにする等の配慮
ユーザーが送られたメール
に記載されたURLをタップ
( 解除用トークン入りURL )
以前に利用したパスコードを破棄
URLスキーム経由で開いて
パスコード解除リクエスト
1. ユーザー登録機能を有する
2. DBへメールアドレスを保持している
1. APIサーバー側と通信する機能を有する
2. URL経由でアプリを開ける設定
送られたパスコード解除
リクエストが正しいか判定
リクエストが正しい場合
パスコードを解除する
iOSアプリを取り巻くネイティブ以外の手法
ReactNativeやReactJSの思想を元に今後利用したい手法を考える
例.	ReSwiftの利用検討とReduxの理解
iOSApp + Redux ReactNative
サンプルアプリ
の開発や記事等
でのアウトプッ
トで試し打ち
活かせる点の模索
Cross	Platformの検証
最初に触れた際の「苦手意識」を克服するために
RxSwiftやReduxについては始めた当初は怖くって仕方なかった
例.	RxSwift	+	MVVM	及び	ReSwift	+	Reduxでの自分なりのサンプルアプリを作ってみる
UIを当てて実際の感じを掴む:
精神的な怖さを少しでも軽くする?目
的でUI実装を当てはめて学習する
⭐ 	自分の好きな分野と合わせる
現場に入っても困らないように:
現場でのプロダクションコードにおい
てもこの時のサンプルに助けられる場
面もあり、良かったと実感できた!
⭐ 	過去の自分に助けられる経験
実装とドキュメントを合わせて徹底的に叩き込む
実務の中でいつ遭遇してもおかしくないものは予習しておきたい
ReSwift:
https://qiita.com/fumiyasac@github/items/f25465a955afdcb795a2
⭐ 	ReduxとSwiftの組み合わせを利用したUIサンプル事例紹介
ReactNative:
https://qiita.com/fumiyasac@github/items/e27a5901dde1dbcb2086
⭐ 	ReactNative+Redux+NativeBaseでつくるサンプル実装をのぞく
RxSwift:
https://qiita.com/fumiyasac@github/items/e426d321fbb8ab846bb6
⭐ 	RxSwiftとUIライブラリの表現を組み合わせたサンプル紹介
基本的な用法や目的パターンを知る
お互いの開発効率を上げられるような取り組み
便利なツールを試してみたり、他の言語や環境を整えるための試し打ち
例.	Postman
https://www.webprofessional.jp/master-api-workflow-postman/
⭐ 	APIの開発がむちゃくちゃ捗る「Postman」の使い方
例.	GoDoc	+	Swagger
https://github.com/swaggo/swag
⭐ 	Swag	(API定義の整理)
積極的にチームのドキュメントにもコミットする
なかなか知見をまとめ切れていない状態を防ぐ&自分の理解を深める
⭐ 	バックエンドAPIやDB構造なんかもまとめて可視化
特に重点的にまとめるのは、紐解きにくい部分:
⭐ 	この元となったのはデザイナー時代の絵コンテの習慣
自分のノートに図解付きでまとめる:
なぜにコード以外の部分にも積極的に目を向けるのか?
1.	ある程度どのような形で動いているかを知ることで事情を正しく把握できるように。
ポイントを明確化するだけでなく、知見として溜まる活動もまた仕事
2.	後回しになりがちな部分に対してのアフターケアやナレッジの共有と伝承。
⭐ 	実際に生で発表を聞いていましたが、むちゃくちゃ素敵な発表でした。
https://www.slideshare.net/akiko_pusu/devsumi-2019
ことばだけでは足りません、描いてシェアして伝えていこう! (Developers Summit 2019の登壇 by 高野明子様)
3.	開発はチームで行うもの。だから仕組みかとノウハウへ昇華する下準備。
https://daily-postit.hatenablog.com/entry/2019/02/25/002330
まとめ
1.	職種間の事情を少しでも知っておくと実務面やアイデア面でも活かせる時がある。
初める際には葛藤や迷いはあるけども違う職種の経験が活かせることはある
2.	学習欲や探究心の炎は常に絶やさない。興味関心&継続の強さを大切にする。
これからも自分ができることはそんなに大きくなくとも、技術でお返しできればと思います
僕自身、始めた当初はまさか仕事にできるとは正直思ってはいませんでした。仕事にしていないにも関わらず、皆様の前
で登壇した時やiOSエンジニアの皆様と関わる中で仕事に1度はしてみたいという気持ちが強くなりました。間違いなく今
の僕があるのは皆様のおかげだと思います。ありがとうございます。
最後に
おまけ
自分のストレングスファインダーから「自分の傾向」を紐解いてみる
Thank	you	for	listening	!

デザイナー→Webエンジニア→iOSエンジニアと渡り歩いた僕なりのSwiftとの向き合い方と生かす戦略