20200110のiOSに関する記事は7件です。

【Swift5】tableViewCellのsubtitleのテキストの書き方

tableViewCellのsubtitleの記述の仕方がわからなかったのでメモとしてここに書きます。

上がタイトルで下がサブタイトルです。

スクリーンショット 2020-01-10 15.15.50.png

//こっちがタイトル
cell.textLabel?.text = object.title
//こっちがサブタイトル
cell.detailTextLabel?.text = object.meaning

ちなみにセルの中のレイアウトの設定の仕方は

ここです。

スクリーンショット 2020-01-10 15.19.41.png

スクリーンショット 2020-01-10 15.19.47.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Voidを返す関数内でのreturnは気をつけた方がいい

追記

  • Warningは正しかったです。

問題

  • 以下はどういう出力になるでしょうか。
func foo() {
  print(#function)
  return // ← この後の処理は一旦無視したいからreturnしておこう

  bar()
}

func bar() {
  print(#function)
}

答え

  • bar() も実行され出力されます。
foo()
bar()

理由

  • 構文上、returnの後の改行は無視されて解釈されるので return bar() となり、 bar() が実行されるため。
func foo() { // 暗黙的に戻り値はVoidを返す関数
  print(#function)
  return

  bar() // return bar() と解釈されるのでbar()は実行される
}

func bar() { // 暗黙的に戻り値はVoidを返す関数
  print(#function)
}
  • 以下が構文上許されているのと同じ意味です。
func baz() -> Int {
  return


  1
}

解決方法

  • セミコロンをつけます。
func foo() { // 暗黙的に戻り値はVoidを返す関数
  print(#function)
  return; // セミコロンをつければ `return ()` として解釈される

  bar() // 実行されない
}

バグ?

追記

  • あれ!Warningの内容が Expression following 'return' is treated as an argument of the 'return' ('return' に続く式は'return'の引数として扱われます) だ!よく一時的な早期returnで遭遇する Code after 'return' will never be executed と勘違いしていた…なのでWarningはあっていますね。

  • return 後の改行が無視されて解釈されるのは言語仕様としては正しいと思いますが、Warningで Expression following 'return' is treated as an argument of the 'return' が表示されるのはバグだと思われます。 あってる?‍♂️

スクリーンショット 2020-01-10 14.08.59.png

  • ちなみにIntの方も表示された…。

スクリーンショット 2020-01-10 14.21.11.png

まとめ

  • Voidを返す関数でreturnを使う場合はセミコロンをつけないと意図しない挙動になる可能性がある。 追記: Warningはちゃんと読みましょう。。。
  • DevSapにて return が無視されるんだけどって話題が出て、僕自身も遭遇した経験があるので今回調査してみました。今までは差分コンパイル時のバグかな?って思って return は避けてコメントアウトするようにしていたのですが、今回やっと原因がわかりました。これは罠すぎる。。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Xcode 11 からWKWebView がstoryboard から使えるようになっていた

WKWebViewがstoryboardで置いてもビルドエラーにならない!

多分、これまでUIWebViewを使っていたデベロッパーであればUIWebViewからWKWebViewに移行する時に、
storyboardから参照しようとするとビルドエラーになるから渋々コードで生成していただろうと想像できます。

現に私もこれまでUIWebViewが使われていたアプリのWKWebViewへの移行タスクを多数取り組んできて
みなさんと同じようにWKWebViewの様々な地雷を踏んできました。

UIWebViewからWKWebViewへのコード上での移行についてはこちらの記事を参考にすればできるようになると思います。
WKWebviewで簡単なwebViewを作成する

移行タスクでは大変お世話になりました。

iOS10のサポートを切る場合、、、

Xcode 11 からWKWebView がstoryboard から使えるようになっていました。
Xcode 10 まで Apple のバグによってWKWebViewをstoryboard から使おうとすると赤のワーニングが表示されて使えませんでした。(Xcode10 だからかiOS10をサポートしている場合だったかは記憶が定かでありません。)
が、Xcode 11 から正式(?)にstoryboardから使えるようになっていました。

UIWebView (depricated)
image.png

WKWebView
image.png

これで晴れてAppleからの通告の「UIWebView使うな」に対する対応が楽にできると思います。

iOS 13における必須対応について

そもそもstoryboardを使っていないプロジェクトやnibを使っていないようなコードのみでUIを実装しているプロジェクトではそもそもこの影響を受けないと思います。

蛇足ですが

WKWebViewなのに「WebKit View」というネーミングはいかがなもんでしょうか。
WKは「Web Kit」の略称だったという記憶がありましたので、これだと「WKView」か「Web Kit WebView」とも読めないことはない気がします。

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Bonfire iOS #7 参加報告(簡単な内容のまとめや感想など)

2020年1月7日に開催されたBonfire iOS #7へ参加させていただき
その際の内容の簡単なまとめと感想を書かせていただきます。

後から資料を見直して補足したり
私見も混ざっているので
間違っている箇所や誤解している箇所があるかもしれません。
もし何かございましたらご指摘いただけますとうれしいです??‍♂️

ヤフーアプリの品質向上戦略

発表者

西 麻扇さん
@mao_nishi

資料

https://speakerdeck.com/nishimao/yahuapurifalsepin-zhi-xiang-shang-zhan-lue

内容

ヤフーアプリが実施している品質向上戦略の中で
実際に実施した中で品質が改善した例を2つのテーマで紹介

  • まずは現状把握から
  • コーディング時間を増やすには

まずは現状把握から

なぜ大事なのか?

まずは現状どうなっていて
それがどのように変化していくのかを計測していくことが大事だと
おっしゃっていました。

具体的には下記の点を挙げられています。

  • 正しいアクションを把握するため
  • ゴールが明確になることで最後まで走りきることができる
  • やるべきことの優先順位をつけることができる

使用しているツール

具体的な計測ツールとして
下記の2つをご紹介されていました。

  • App Analytics
  • XcodeのOrganizer
App Analytics

Appleが提供している公式のツールで
アプリのクラッシュ数などを把握することができます。

私は使用したことがなく
会場でのアンケート結果も
使用経験者は1割くらいでした。

https://developer.apple.com/jp/app-store-connect/analytics/

XcodeのOrganizer

XcodeのWindow > Organizerから見ることができ
こちらはアプリのクラッシュの詳細を見ることができます。

こちらも私は使用したことがなく
アンケートでも1割くらいの方が使用経験があるようでした。

実際Crashlyticsなどの方がより詳細を把握できて
便利ではないかという風におっしゃっていました。

Xcode11の新機能 Metrics

しかし
Xcode11からMetricsという項目が登場し
リリース済みのアプリの様々な統計情報を
取得することができるようになり
これが大変便利だとのこと。

※ ただし、取得にはユーザの許可が必要になります。

https://help.apple.com/xcode/mac/current/#/devb642b28ac

これを活用することで品質に関わる下記の項目を把握できます。

  • バッテリー消費量
  • 起動時間
  • ハング率
  • メモリ消費
  • ディスク書き込み

ここでおっしゃられたことの中で
「これらが低ければ低いほどAppleは品質の良いアプリだと考える」
という言葉が個人的には印象的でした。

当たり前と言われれば当たり前なのですが
改めて言われると
「なるほどこういう点をより意識する必要があるんだな」
と思い直すことができました。

【問題】アプリをまたがって一覧でデータを見ることができない

Xcode上ではアプリごとの統計を見るために
クリックして一つ一つ見なければならないのが面倒だとおっしゃっていました。

これは複数のアプリをリリースしている大きな企業ならではの悩みだなと思いました。

そこで対策としてApple Scriptを作成して一覧データを自動取得しているとのこと。

https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html


詳細は作成者の
@kazuhiro4949さん
がお詳しいとのこと。

ここでおしゃっていたことなのですが
各アプリのコミット数も見ているとのこと。

これはコミット数が多ければ多いほど
品質を向上させるための施策がされているのではないか
という考えからきているようです。
(人によって一つのコミットの大きさが変わってくると思うので
そこらへんのルールがあるのかちょっと気になりました?)

品質を向上させるために最終的に可視化している項目

下記の項目を可視化しているとのことでした。

スクリーンショット 2020-01-09 4.52.26.png

この中でOSS利用数を見ていますが
Cocoapodsの使用数が多いと
Carthageの利用を推奨するようにしているとのことでした。
これはCarthageを利用することでビルド時間を削減するためです。

コーディング時間を増やすには

なぜ大事なのか?

下記の点から大事だとおっしゃっていました。

  • リファクタリングに時間をかけることができる
  • 精神的余力が生まれる
  • よくないコードを見逃さなくなる

コーディング時間を減らす要因

これを見た時
正直「あーこれこれ」と内心思ってしまいましたw

  • バグ対応
  • レビュー指摘での手戻り対応
  • すり合わせMTG
  • 集中力の切れた状態での稼働
  • 平行開発案件がたくさんある

特に平行開発案件がたくさんあると大変

この中でも
平行開発案件があることによる弊害が大きいとのことで
これを解決したことで
どういう効果があったかを紹介されていました。

以前の問題

開発者がfeatureブランチを切って
開発が完了したらmasterへマージする
Github flowを利用していたとのこと。

Github flowについて
http://scottchacon.com/2011/08/31/github-flow.html
https://gist.github.com/Gab-km/3705015

これを平行開発で利用していると
各ブランチでCIを回してうまくテストが通っていたとしても
結合テスト時にうまく動作しないことにより
調査と修正という手戻りが発生してしまうことがあったとのこと。

現在の方法

そこで

ブランチの廃止 + ペアプロで常時レビュー&コミット

でみんなで1つの機能を作成するようにスタイルを変更したそうです。

結果として

  • 常に最終成果物でCIを回すことができる
  • 常にコードレビューがされていることから手戻りが減る
  • 実装完了即マージという状態でスピードが上がる

などが実現できたとのことでした。

「開発が遅くなるのでは?」
という質問をされることが多いとのことでしたが
結果的に手戻りが減るのでむしろ早くなるとおっしゃっていました。

また
開発途中のリリースに関しては
フィーチャーフラグを導入して
必要になるまでは見えないようにフラグを
立てるようにしているとのこと。

フィーチャーフラグについて

Googleやfacebookでも導入されている
ブランチを分けずに機能をmasterブランチへ実装していく中で
機能のオンオフを切り替えられるようにフラグを設定しておく手法です。
https://martinfowler.com/articles/feature-toggles.html

「コンフリクトが多く発生するのでは?」

という疑問が湧いたのですが、
他の方が挙げられていた質問への回答の中で

ストーリーで上手くやることを分けて
同じ箇所の修正が発生しないようにしている

と回答を聞くことができました。

私もGithub flowを利用していることが多く
featureブランチが多すぎる問題や
結合したらなぜか動かない問題などに直面した経験があり
その際にもブランチ廃止してフィーチャーフラグを導入する案も出ていたので
実際の事例が知れて大変参考になりました。

切り替えるに至った経緯や
切り替え時にぶつかった課題や解決方法など
もっと深い話が聞きたいなと思いました。

すべての時間をコーディングに

最後に出てきたこの言葉がとても刺さりました。

コーディングをすることで
リファクタリングの時間が得られて
アプリの品質の向上につながることに加えて

アプリについて考える時間が増えることで
より良いサービスの提供の仕方や機能などにも目を向けていくことができ
デザイナーさんや開発チーム以外の方とのコミュニケーションも活発になって
さらにアプリが良いものになっていくという相乗効果も出てくるのではないかなと
個人的には感じました。

(単純にコーディングするのが好きなので
集中してコーディングできる時間が増えるのは嬉しいことだな
という思いもあったりしますw)

PayPayフリマ iOS

発表者

大西 智也さん
@tomoya_onishi

資料

上がったら反映します

PayPayフリマでできること

  • 商品の出品
  • PayPayとの連携
  • ヤフオクからのリスティングなど

iOSチーム

  • 最大で10人いた
  • ペアプロで開発を進めている
  • iMacを使用

ペアプロの進め方

  • ディレクション1人で他は全員ペアで実装
  • ペアは毎日ローテーションしている

開発スタイル

  • XP(エクストリームプログラミング)

  • ストーリー制

  • 開発と受入れテストがセットになっていてエンジニアが開発を完了すると、ディレクションが受け入れをする

  • 週1回集まって全メンバーでストーリーの確認をする。仕様の共有やどう作るかを議論する。

  • TDDで一人が失敗するテストを書き、もう一人が実装を進める。ストーリーごとに役割を交代する。

ペアプロの効果

  • 属人化を防ぐ
  • スキルの共有ができる
  • 新卒でもペアに入るので成長が早い

開発の方針

  • Noドキュメント
  • Noコードレビュー
  • Noブランチ

Noドキュメント、Noコードレビューは
ペアプロを実施することで達成できているとのことでした。

こういった仕組みで品質を担保しつつ
不要な作業を省いて常に良いスピードも保てているようです。

XPという言葉はよく耳にしていて興味がありましたが
ここまでの大きな規模で実践されている例を初めて聞き
単純にすごいなと思いました。

もっと細かく見ると
イメージとは異なった点や
そこをどう調整して取り組んでいったのかなどの話が
たくさんあると思うので
ぜひさらに深いお話を聞いてみたいなと感じました。

リリースまでの開発の進め方

PJ発足当初

技術的な基盤の整備

背景

仕様やデザインが決まっていないなど
不確定な要素が多かったため
後々面倒になるけれども必要な

  • プッシュ通知
  • URLスキーム
  • カラースキーム

などの仕組みの作成を行っていたそうです。

開発環境構築の最強のMakefileの作成

さらに同じ時期に
誰でもコマンド一つでシミュレータが起動ができるまでの
準備をしてくれる最強のMakefileを作成することで
新規参入時の障壁を少なくすることができたそうです。

仕様が決まってきたら(デザインはできている)

APIのモックを作成し、UIの作成を進めていったそうです。

中盤以降になると、
iOSエンジニアがBFFを作成して進めている時期もあったようです。

BFFについて
https://www.atmarkit.co.jp/ait/articles/1803/12/news012_2.html

設計、テスト

設計

クリーンアーキテクチャー

テストを書いている場所

Presenter, Repository, UseCase

品質を担保するためのテスト

  • ペアプロでユニットテスト
  • ストーリーの受け入れテスト
  • リリース前にみんなでスモークテスト
  • UIテストを定期実行(モンキーテスト)

この中で
ユニットテストの単位は結構細かくし
gitのpre-push時に必ずテストを通過させるようにしているとのことでした。

また
UIテストに関しては
UIの変更が多いため
あまり細かいチェックは行わず
ランダムに動かして成功すればOKくらいの単位で
実施しているとのことです。

開発の進め方を
時系列に説明して頂くことでイメージしやすく
とてもわかりやすい内容でした。

上記のような時期の違いによって
XPへの取り組み方がどう変わっていったのかなど
もっと深い話を聞いてみたいなと思いました。
(最大10名というところがちょっと気になりましたw)

Yahoo!乗り換え案内 DarkMode対応

発表者

田中 達也さん
@tanakasan2525

資料

https://speakerdeck.com/tattn/yahoo-cheng-huan-an-nei-falsedakumododui-ying
https://techblog.yahoo.co.jp/entry/20191212788765/

iOS13正式リリース日にダークモード対応

なぜ?

  • WWDC2019に参加してAppleがダークモードにかなり力を入れていると感じ、App Storeで特集されるチャンスだと考えた
  • 乗り換えアプリは日常で使用されるものなので、よりアプリに愛着を持ってもらうために好きなモードで使ってもらいたいというデザイナーさんの思いがあった

App Storeの特集という視点はなかったので
新しい気付きを得られました。
長くアプリをリリースしている方ならではの視点だなと感じました。

工数の見積もり

どのくらいで終わるのかがわからないため仮デザインを作成してもらい
まず対応時間を計測してあとは画面数に応じてざっくり計算

作業分担

1画面1Storyboardなので比較的シンプルにタスクを分けることができた。
デザイナーさんも日頃からXcodeで色設定をしていたので静的な部分は作業を割り当てることができた。

人がたくさんいらっしゃるのでタスクの分割大変なんだろうなと思いましたが
画面の設計がシンプルで切り分けやすいのは良さそうだなと思いました。
特にStoryboardのコンフリクト時の辛みはすごい感じました。。。

Storyboardを使用していることによる決断も

Asset Catalogでライトモード、ダークモード両方を一括管理できることは便利だが
iOS11以上でないとサポートされていなかったためiOS10のサポートを切ることに。

画像データの作成と色の設定を同時並行で実施する

500以上の画像があり、デザイナーさんが大変。
色設定と同時並行で実施することで
負担の軽減と作業が止まることを防いだとのことです。

バージョンの違いによる違い

iOS13SDKにした結果
iOS12以下で設定を上手く反映してくれないことが
あったようです。

  • UILabelのisOpaqueがYesで背景色が未設定だとラベルが真っ黒になる
  • Xib/StoryboardでAsset Catalogで色を設定している場合、コードで設定した値を上書きしてしまう

など

こういうバージョン差異は再現させるのも難しく
対策をしたら片方がおかしくなったりもぐら叩き状態になることがあるので
非常に辛いなと感じました。

ドッグフーディングは大切

上記のような不具合は見つけづらいものですが
これを早く見つけられた要因として

社内でドッグフーディングしやすい環境を構築し
誰でもフィードバックを送れる状態にしておくこと

が大切であるとおっしゃられていました。

ドッグフーディングについて
https://makitani.net/shimauma/dogfooding

ヤフーでは
AppFeedbackというアプリを開発し
ドッグフーディング環境を構築しているとのことでした。
https://techblog.yahoo.co.jp/oss/appfeedback/

つい最近
私のチームでも作成したものに対して
フィードバックが少ないという議題が出ていたので
大変興味深かったです。

開発中は開発チームという枠内で考えがちでしたが
より多くの人が簡単に触れるようになることで
不具合の早期発見だけではなく
多くの意見が得られることでUXの向上にもつながるんだなと感じました。

普段目が向けられていなかったことだったので
多くの学びがありました。

新機能はエンジニアが導入を進めるべき

新機能について一番詳しいのはエンジニアのはずということ。

そして新機能を導入することで

  • UXが向上してユーザは幸せ
  • ユーザが増えて会社は幸せ
  • 新しいことができてエンジニアは幸せ

というWin-Winの関係を構築することができる
とおっしゃっていました。

具体的には
実装してみてSlackで公開したりアプリを配布することで
開発者以外の人も興味を持ってくれて導入が促進される
とようです。

ここはまさにその通りだなと思いました。

全体を通して
体験に基づいた発表はすごいリアルで
自分も対応した時にこんなことが起きるんだろうなということが
イメージできてとてもわかりやすい内容でした。
また、周りを巻き込むための取り組みなども大変参考になりました。

コードを書きながら同時に設計していくためのiOSアプリ開発方針

発表者

林 和弘さん
@kazuhiro494949

資料

https://speakerdeck.com/kazuhiro4949/kodowoshu-kinagaratong-shi-nishe-ji-siteikutamefalseiosapurikai-fa-fang-zhen

今回の内容について

今回の内容は
2019年12月のアドベントカレンダーに
記載した記事を元にされていたようです。

https://techblog.yahoo.co.jp/entry/20191202785270/

記事の要点

実現したいこととして

  • 実際の実行結果を触りながら、心地よく動くコードを試行錯誤して書く
  • ユニットテストを頻繁に実行しながら、実装を固めていく

それを実現するまでの課題として

  • 一回のユニットテスト実行が無視できないほど遅い
  • アプリが動いているプラットフォームの実際の挙動を完全には把握しきれない
  • 成果物の最終的な仕様は作りながら決まっていき、リリース後も変化してしまう

そしてこれを解決する方法として

  • 実装の試行錯誤で動くようになったプロダクトコード(動いていればOK)
  • ユニットテストのテストケース(簡単にテストが書けていればOK)
  • ベースとなっているプラットフォームの作りが変更に対応しやすくなっていればOK

という正しい設計の判断基準があれば良いのではないかという内容が書かれています。

上記を踏まえての提案

今回の発表では
下記の3つを提案されています。

  • システムフレームワークを中心に必要に応じて設計していく
  • ユニットテストを設計の良し悪しの評価にする(テストの書きやすさ)
  • レイアードアーキテクチャは使わない

全体として
強調されてた点としては

将来的にも仕様は変わっていくものなので
最初にかっちりと設計を固めるのではなく
変更に対応できるように最低限守ることは守り
変更に応じて設計も簡単に変更できるようにしておく

ということなのかなと個人的には感じました。

そして変更に対応しやすい設計を積み上げていくためにも
テストを作成し、テストが簡単に書けるように保っていくことが
正しい設計ができている判断基準とする

ということも強調されていたのかなと思っています。

提案の背景

システムフレームワークを中心に

iOS SDKを使ったUIのライフサイクル

iOS SDKのUIの画面遷移、ライフサイクル、アニメーションなどは
システム側で複雑に制御されているため
そのためロジックを切り出して自前で制御をしようとすると
オブジェクトやイベント管理が複雑になってしまう。

iOSアプリでのユニットテストはだんだん遅くなる

ユニットテストを実行するには

アプリターゲットのビルド->テストターゲットのビルド->ユニットテストの実行

というサイクルが必要。

その中で
型推論を多く用いたり
コードの依存関係が複雑になるにつれて
ビルド時間が長くなったり

非同期テストが多いことや
システム側のライフサイクルに合わせなければいけないケースが多く
一つの関数としてテスト単体化することが難しい。

現実のプロダクトでは複雑なクラス設計に時間を費やせない

上記のような要因から

  • 心地よくアプリを作って維持すること
  • ユニットテストを必要十分に作って維持すること

は難しいとおっしゃっていました。

下記のシンプルな方針で進めていく

そこで
開発が進む(コードが大きくなる)につれて
下記の3つのことを順に考えていくのがシンプルで良いのではないかとのこと。

  • ViewとViewControllerでクラス分割
  • DIによる集約
  • Embedded Frameworkによるモジュール分割

ViewとViewControllerでクラス分割

複雑なことは考えずに
UIKitを活用してメモリ管理などはシステム側に任せてしまう。

ロジックが複雑になってきたら
Container ViewControllerなどを利用して
そこの部分だけを切り出していく。

実装の流れとしては

ルートVC上はに動くコードをベタ書き
↓
ロジックが増えてきたらユニットテストを実装
↓
ロジックが複雑になってきてテストケースが複雑になったらVCやViewに分ける

とし

全体を規定するアーキテクチャは導入しない
ことを強調されています。

最初から型にはめてしまうのではなく
あくまでUIKitを中心に考え
ユニットテストの複雑さを基準にして
必要になったらモデルに切り出していく。

この進め方が良いのではとおっしゃっていました。

ここはテスト駆動開発の

レッド->グリーン->リファクタリングを繰り返していく中で
最小限の設計をしていく

という考えに近いなと感じました。

ユニットテストのテストケースをクラス分割の判断基準にする

上記の中でも
テストケースを判断基準にして
複雑だと感じるようになったら
モデルに切り出すということに関して

逆にユニットテストが必要ない程度のものならば
クラス設計を考える必要がないのではないか
ということもおっしゃっていました。


ただ、全てを一つの関数にするという意味ではなく
ロジックが変わらない範囲で
プライベートメソッドやクラスへの分割は必要とのことでした。

DIの集約

切り出したクラスをどのように利用するかという点において
DIについて話されていました。

テストしたいロジックをまとめてクラスに切り出して
それを抽象化(プロトコル化)した上で
元の使用していたクラスに渡してあげるのが良いのでは
とおっしゃられています。

依存の切り出し方
中で使っているオブジェクトのプロパティ化
↓
ロジックを外からDIする(外のクラスにロジックを移動させる)
↓
初期化専用クラス(いわゆるファクトリークラス)で複数のクラスを動的に集約する

といったことを挙げられています。

これも全て行うという訳ではなく
切り出したクラスの数によって
どこまで考えるかは判断していくのだと思います。

DIを行う場所
  • 初期化時に渡す
  • メソッドの引数として渡す
  • プロパティで渡す

を挙げられています。

一般的には初期化時に渡すのが好ましいとされていますが
テストができるならば案外どこでも良いのではないかという風に
おっしゃられていました。

Storyboardを利用しているとUIViewControllerへのDIは
プロパティで行う必要が出てきたりするので(iOS12以下の場合)
そこは状況に応じてなんだろうなと私も思いました。

そこでも守るべきこととして

DIはプロトコル経由にする

ということをおっしゃられており
これはさらにクラスを切り出していった結果
モジュールに切り出す時にも変更に対応しやすくするためです。

ここでも変更への対応のしやすさを強調されているなと感じました。

また
まずテストを書ける状態にすることが大事であり
シングルトンでもひとまずDIできるようにしておき
あとからリファクタリングする
とおっしゃっていました。

動ける状態にしてからきれいな状態にする
というテスト駆動開発の考えに近いと思いました。

同時に
きれいにしながら動ける状態を作っていくと
動かせるまでの時間が長くなるので
いつまでも終わらない感覚に陥って辛くなる。。。
という経験が何度もあったことを思い返していました。

この後にもテストが書けることを中心に考え
テストが書ければシンプルな設計で良いのでは
ということを強調されていたように感じました。

DIの方法としては

ロジックを切り出す
↓
外から代入する
↓
プロトコル経由にする

というサイクルを繰り返すして
クラスを集約していくという
ルールを守っていく以外の
複雑なクラス設計などについ難しく考えなくよいのではないか
とのことでした。

以前の私も最初から設計や形を決めていくことが多く
その中でその形に実装を寄せていってしまう傾向にあり
余計な複雑さを持ち込んでしまうことが多々あったので
この考えにはすごく共感できました。

ユニットテストの実行サイクルを遅くしないためのEmbedded Framework

さらにクラスの分割が進んでくると
依存関係が増えてビルド時間が増えたり
テストケースが増えることで
ユニットテストの実行サイクルが遅くなる。

そこを矯正するためにも
モジュール分割(Embedded Framework)を活用していく。

ここがレイヤー化のポイントである。

ということをおっしゃられていました。

ただし
ここでもどういう形でモジュールにするのかにこだわる必要はなく

  • チーム内でコンフリクトが起きない
  • テストの実行や実装が複雑にならない

といった不利益が起きない範囲で考えられれば良いのでは
というようなことをおっしゃっています。

ただ
将来的にモジュール化をしていく想定で
実装上意識すべきこととして
下記のことを挙げられていました。

  • クラス間の依存をできるだけ減らす
  • 循環的な依存をなくす
  • 継承ではなく集約(DI)でコードを使い回す
  • プロトコル経由でDIする

最後に

フレームワークの都合などにより
最初にきれいな設計を構築してみても
アプリを心地よく作って維持することや
必要十分なユニットテストを作って維持することはとても難しい。

だからこそ必要以上に複雑に考えず
システムの仕組みに乗っかっていく中で
複雑になってきたら
クラスを分割して設計を都度見直していく。

そうすることで
心地よいUXの提供に集中できるのではないか。

というようなことをおっしゃっていました。

どうやって実装するのかに費やす時間が増えると
UXなど何を提供するのかについて使える時間は相対的に減る
ということについて改めて考えることができました。

全体を通して
とても学べることが多くあったことに加えて
共感できる点もたくさんあって
聞き応えのある内容でした。

全体の感想

大きな会社、そしてIT企業としては歴史のある会社として
やはりしっかりとした仕組みや開発スタイルが確立されているすごさを
感じました。

ただ、ここまで来れたのも
相当な試行錯誤が繰り返されてきた結果であり
今でもその連続なんだろうなとも感じました。

こういう仕組みや開発スタイルについて考えることが
好きなんだということに最近気がつき
どう学び、どう身につけ、どう広めていくことができるのかについて
とても興味を持っているため
学びが多く非常に充実した時間を過ごさせたと私は感じています。

今後、もっと深い経緯を聞く機会や学べる機会があれば
率先して参加したいなと思っています。

このような素敵な会を開催してくださった
運営の皆様、登壇された皆様
本当にありがとうございました?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

外出先でWebサイトをデバッグする

はじめに

PCやUSBケーブルなどを使わずに、外出先でモバイルブラウザ向けの開発コンソールであるErudaを任意のWebサイトで呼び出します。このErudaを使うことでChrome Dev ToolsのようにDOMやリソースなどを表示することができます。
Erudaを使ったデバッグ方法については割愛しますが、
ブックマークレットiOSのショートカットを使ってモバイルブラウザ上でErudaを簡単に呼び出すことができます。

ブックマークレット

最も簡単なのが、以下のGistにあるブックマークレットをブックマークに登録し、iPhoneやAndroidなどのモバイルブラウザから呼び出す方法です。一応、PCのブラウザからも呼び出せますが、素直にChrome Dev Tools を使った方が良いです。
Eruda Bookmarklet - GitHub Gist

任意のサイトを開いて、この登録したブックマークを呼び出すことで、ブラウザの右下にErudaの歯車アイコンが表示されます。
このアイコンをタップすることで、Erudaの開発コンソールが開きます。

iOSのショートカット

こちらは、iPhone限定(iOS12以上)の方法です。
主に、SafariブラウザやSFSafariViewController、ASWebAuthenticationSessionを使ったブラウザで利用することができます。

このショートカットでは、Erudaのjsライブラリを読み込むJavaScriptを任意のWebサイトで実行します。

JavaScriptの実行処理

以下のコード上のブラケットで囲っている部分は変数で、Erudaのjsライブラリ本体をテキストとしてショートカット内部で設定しています。
また、Eruda本体のjs以外に、eruda-dom.jseruda-timing.jserada-code.jsの3つのプラグインを上記のブックマークレットと同様に設定しています。プラグインの詳細はこちらを参照してください。

// eruda本体のjs
{eruda.js}

// erudaのプラグインのjs
{eruda-dom.js}
{eruda-timing.js}
{eruda-code.js}

// erudaの初期化
eruda.init();

// erudaのプラグインの読み込み
eruda.add(erudaDom);
eruda.add(erudaTiming);
eruda.add(erudaCode);

// JavaScriptの完了コールバックの呼び出し
completion(true);

ショートカットの実行方法

作成したショートカットの共有リンクをタップしてショートカットをインストールします。
その後、任意のWebサイトをSafariなどで開き、共有ボタンからErudaというショートカットを呼び出せば、ブラウザの右したにErudaの歯車アイコンが表示されます。

image.png

作成したショートカットの詳細については、インストールしたショートカットの内部を参照してください。

参考サイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[iOS] UITextViewにハイパーリンク�を設定する〜テキストの一部を正規表現で抽出して〜

これはアプリのUITextViewの一部にハイパーリンクを設定する実装例となります。
取得する文章データから正規表現でリンクを抽出してハイパーリンクを設定します。

ex.swift
func setup(text: String) {
    // リンク設定
    textView.linkTextAttributes = [
        NSAttributedString.Key.foregroundColor: UIColor.maiFontBlue,
        NSAttributedString.Key.underlineStyle: 1
   ]

    // リンクの抽出
    var hyperlinks: [(link: String, word: String)] = []
    do {
        let regex = try NSRegularExpression(pattern: "<a href=\"(.*?)\".*?>(.*?)</a>")
        let nsString = text as NSString
        let matches = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
        let links = matches.map { nsString.substring(with: $0.range(at: 1))} // 正規表現のグループ1(1つ目の"(.*?)"部分)を抽出できる
        let words = matches.map { nsString.substring(with: $0.range(at: 2))} // 正規表現のグループ2(2つ目の"(.*?)"部分)を抽出できる
        links.enumerated().forEach { index, link in
            if words.count > index {
                let hyperlink = (link: link, word: words[index])
                hyperlinks.append(hyperlink)
            }
        }
    } catch {
        // Nothing
    }

    var attributes: [NSAttributedString.Key: NSObject] = [:]
    attributes[NSAttributedString.Key.foregroundColor] = .black
    textView.attributeText = NSAttributedString(string: text, attributes: attributes)

    // ハイパーリンクの設定
    if hyperlinks.count > 0 {
        let atttributedText = NSMutableAttributedString(attributedString: textView.attributedText)
        let nsText = atttributedText.mutableString
        hyperlinks.forEach { hyperlink in
            let nsrange = nsText.range(of: hyperlink.word)
            atttributedText.addAttribute(.link, value: hyperlink.link, range: nsrange)
        }
        textView.attributedText = atttributedText
    }

}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React NativeでiOSアプリを環境ごとに共存させる

背景・動機

業務でReact Nativeを使ったアプリを開発しています。
実機でアプリをテストする際に、毎回環境を切り替えてビルドする手間がかかっていました。
環境ごとに別名のアプリをビルドし実機にインストールできるようにしたので、備忘録も兼ねて投稿します。

概要

アプリからバックエンドのAPIサーバや、WebViewを使ってWebサーバへアクセスしており、バックエンドのサーバには、Development、Staging、Productionの3つの環境があります。

今回は、アプリもバックエンドのサーバと同様にStaging環境を追加し、Debug、Staging、Releaseでそれぞれ別名のアプリをビルドし実機にインストールします。

以下のような状態を目指します。

iPhone.png

1. アプリのConfigurationにStagingを追加

デフォルトの状態ではアプリにはDebugとReleaseの2種類の設定しか用意されていませんので、Stagingの設定を追加します。

  • Xcodeを開き、PROJECT > Info > Configurationsの「+」をクリック。
  • Duplicate "Release" Configurationを選択し、Stagingと入力します。

image.png

2. Reactの各ライブラリがReleaseビルドを参照するようにPathを追加

ConfigurationにStagingを追加するだけではビルドに失敗してしまいます。
Reactをはじめとする外部のライブラリも、Debug、Releaseの2種類の設定しか対応していないためです。
今回は外部のライブラリはReleaseを参照するようにPATHを追加します。

2-1. Header Search PathsにPATHを追加

  • TARGETS > アプリ名 > Build Settings > Search Paths > Header Search Pathsを開く。
  • Stagingの値に$(BUILD_DIR)/Release-$(PLATFORM_NAME)/includeをnon-recursiveで追加。

スクリーンショット 2020-01-10 0.41.52.png

2-1. Library Search PathsにPATHを追加

  • Header Search Pathsのすぐ下にあるLibrary Search Pathsを開く。
  • Stagingの値に$(BUILD_DIR)/Release-$(PLATFORM_NAME)をrecursiveで追加。

スクリーンショット 2020-01-10 0.42.19.png

同様の修正をTARGETS > アプリ名Testsにも行います。

3. 環境ごとにアプリ名とバンドル名を変更する

同一端末にアプリを共存させるためには、バンドル名が異なっている必要があります。
アプリ名も環境ごとに変更した方が、混乱せずに済むと思いますので、修正します。

3-1. ユーザー定義変数を設定する

  • TARGETS > アプリ名 > Build Settingsの「+」をクリック。
  • Add User-Defined Settingをクリック。
  • BUNDLE_IDENTIFIER_SUFFIXDISPLAY_NAME_PREFIXを追加(名前は任意で構いません)。
  • 各Configurationごとに、以下のキャプチャ画像のように設定します。

スクリーンショット 2020-01-10 0.56.39.png

3-2. バンドル名、アプリ名にユーザー定義変数を追加

  • TARGETS > アプリ名 > Info > Custom iOS Target Propertiesを開く。
  • Bundle identifierの値を$(PRODUCT_BUNDLE_IDENTIFIER)$(BUNDLE_IDENTIFIER_SUFFIX)に設定する。
  • Bundle display nameを$(DISPLAY_NAME_PREFIX)アプリ名に設定する。

スクリーンショット 2020-01-10 1.05.33.png

4. 端末にインストールする

  • macにiPhoneを接続しアプリをビルドします。
  • Edit Scheme... > Build ConfigurationにStagingが増えていますので、適宜変更してビルドしてください。
  • Debugビルドを実行するとアプリ名にDevが追加されたものが、Stagingビルドを実行するとStgが追加されたものがインストールされます。
  • Releaseビルドは今までと同じように、アプリ名に何も追加されずインストールできます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む