UIButton.Configuration.Sizeの各サイズごとのデフォルト状態での高さ

iOS 16.1シミュレーターで確認してみた。

UIButton.Configuration.Size

@2x @3x
UIButton.Configuration.Size.large 50.5 50.33…
UIButton.Configuration.Size.medium 34.5 34.33…
UIButton.Configuration.Size.small 28 28
UIButton.Configuration.Size.mini 28 28

特別にHuman Interface Guidelinesの44x44ポイントのヒットターゲットが意識されている・遵守するようになっているわけではないのか。

Buttons - Menus and actions - Components - Human Interface Guidelines - Design - Apple Developer

Make buttons easy for people to choose. On a touchscreen, buttons need a hit target of at least 44x44 points to accommodate a fingertip.

iOSシミュレーター・Androidエミュレーターにアプリをインストールだけする(起動までしない)方法

なぜ

アプリの初回起動時専用の特別な処理や画面遷移を行うケースで、そのデバッグ実行・動作確認をするため。

iOS

まずインストールするためのアプリは Build For Running でビルドしておく。次にシミュレーターを起動しておいて

xcrun simctl install booted <~~.appのパス>

のコマンドを実行する。

もしくは、シミュレーターのウィンドウに ~~.app をFinderからドラッグ&ドロップする。

Xcodeのスキーム設定の Wait for the executable to be launched が使えるのでは、と一瞬考える。しかしこれはシミュレーターにインストール済みのアプリには使えるのだが、まだインストールされていないアプリの場合は、アプリのインストールまではやってくれないので、ただ待つだけ(何も起きない)状態になる。ので、別途自分でインストールしてあげる必要がある。

UserDefaultsやKeychainも含めてまっさらな初回起動状態の再現のために、シミュレーターのメニューの Device -> Erase All Content and Settings… も便利。

Android

エミュレーターを起動しておいて

gradlew installDevelopDebug

のコマンドを実行する。DevelopDebug の部分は使いたいbuild variantを指定する。こちらはエミュレーターではなく実機接続でも動作する。

iOSシミュレーター同様に、エミュレーターのウィンドウにapkファイルをドラッグ&ドロップでもインストールできる。

Mockolo 1.7.0のビルド済みバイナリがarm64にしか対応していない

https://github.com/uber/mockolo/releases/download/1.7.0/mockolo.tar.gz に含まれる mockolo バイナリがarm64アーキテクチャーにしか対応していなかった。これだとAppleシリコンMacでは実行できるが、Intel Macでは実行できない。

$ file mockolo
mockolo: Mach-O 64-bit executable arm64

その前はどうかと思って1.6.3を確認してみたら、そちらはx86_64だけだった。これは本当はx86_64でもarm64でも実行できるユニバーサルバイナリになっていてほしい。

ということで修正PRを出してみている。SwiftPMでは swift build の引数に --arch arm64 --arch x86_64 を足すだけでユニバーサルバイナリにできるので、それをやっただけです。

github.com

追記

このPRを含む1.7.1がリリースされていました。Intel Macの方もAppleシリコンMacの方もどうぞご利用ください。

FirebaseのSwiftPM対応に伴ってGoogle Tag ManagerもSwiftPMでインストールできるようになっていた

iOS(ないしAppleプラットフォーム全般)のFirebaseといえばこれまでインストール方法はCocoaPodsが基本だったが、バージョン8.0.0からSwiftPMでもインストールできるようになっている。

さて、Firebase Analyticsと組み合わせて使えるツールとしてアプリ向けのGoogle Tag Manager(以下GTM)もあるのだが、これもSwiftPMで扱えるのか。8.0.0がリリースされた直後の2021年5月時点ではサポートされていなかったのだが、2021年8月からひっそりとサポートされるようになっていた。

ということでGTMのSwift Packageは https://github.com/googleanalytics/google-tag-manager-ios-sdk で公開されているので、これを使えば良いことがわかった。


ところでGTMのSwift Packageはバイナリとしては https://dl.google.com/firebase/ios/tagmanager/swiftpm/7.4.0/GoogleTagManager.zip というzipを参照していて、これはCocoaPods向けの https://dl.google.com/firebase/ios/tagmanager/405c0e6ab8f653b7/GoogleTagManager-7.4.0.tar.gz とは別物になっている。中身を確認してみたところ、CocoaPods向けバイナリ(xcframework)では TagManagerResources.bundle というバンドルがxcframeworkのResourcesに含まれていて、podspecでもそのバンドルがアプリに追加されるようになっている。

https://github.com/CocoaPods/Specs/blob/a26c0002e6e8fe7fcd3059ec699d1f2e05f71400/Specs/9/5/6/GoogleTagManager/7.4.0/GoogleTagManager.podspec.json#L29-L31

TagManagerResources.bundle の中身は Info.plist を除くと TAGRuntime.js.dat というファイルが1つだけだった。SwiftPM向けのxcframeworkを確認してみると、そこにはResourcesも TagManagerResources.bundleTAGRuntime.js.dat も見当たらない。これはちゃんと動くのだろうかと不安になったが、Mach-O Executables · objc.io に書かれている手段で、otool を使って中身をチェックしてみた。

$ xcrun otool -v -s __TEXT __cstring -arch arm64 GoogleTagManager.xcframework/ios-arm64_armv7/GoogleTagManager.framework/GoogleTagManager | grep TAGRuntime
0000000000001857  T@"TAGRuntime",&,N,V_runtime
GoogleTagManager.xcframework/ios-arm64_armv7/GoogleTagManager.framework/GoogleTagManager(TAGRuntime+Script.o):
GoogleTagManager.xcframework/ios-arm64_armv7/GoogleTagManager.framework/GoogleTagManager(TAGRuntime.o):

TAGRuntime+Script.o というのがいかにも怪しい(それっぽい)のでセクションの中身も見てみる。

$ xcrun otool -v -s __TEXT __cstring -arch arm64 GoogleTagManager.xcframework/ios-arm64_armv7/GoogleTagManager.framework/GoogleTagManager | grep TAGRuntime+Script -A2
GoogleTagManager.xcframework/ios-arm64_armv7/GoogleTagManager.framework/GoogleTagManager(TAGRuntime+Script.o):
Contents of (__TEXT,__cstring) section
000000000000000c  \nvar aa,ba=this,h=function(a,b){var c=a.split("."),d=ba;c[0]in d||!d.execScript||d.execScript...

ということで、いかにもJavaScriptらしきものが確認できて、この内容は TAGRuntime.js.dat と合致していた。SwiftPM向けのバイナリではスクリプトがコード中に埋め込まれていたのですね。めでたしめでたし。

App Storeの定期購読・無料トライアルの基準タイムゾーンはUTC

App Store Connectのドキュメント(ヘルプページ)にはこうあります:

自動更新登録は、1 か月間の日数ごとではなく、最初の購入の暦日と同じ日に更新します。たとえば、カスタマーが 1 か月の無料トライアルを 1 月 7 日に開始する場合、トライアルが終了するのは 2 月 7 日です。翌月に同じ日が存在しない日に 1 か月のトライアルを開始した場合、トライアルが終了するのは翌月の末日ですが、利用可能になると元の日付に戻ります。たとえば、カスタマーが 1 月 30 日に登録すると、次の更新日は、2 月 28 日 (閏年の場合は 2 月 29 日) で、その次は 3 月 30 日になります。

これだけだと「そうですね」となるのですが、仕事で見かけた事例によると、どうも日時はUTCタイムゾーンを基準としているようです。日本時間などユーザーのローカルタイムゾーン基準でないことで、次のようなややこしいことが発生し得ます。

  1. 日本時間の3月1日 午前9時(UTC 3月1日 午前0時)に無料トライアルを開始
    • 無料トライアルの終了日(課金開始日)は4月1日
  2. 日本時間の3月1日 午前8時(UTC 2月28日 午後11時)に無料トライアルを開始
    • 無料トライアルの終了日(課金開始日)は3月28日で、4月1日ではない!

日本時間では同じ3月1日に無料トライアルを開始しても、たった1時間の違いで無料トライアルの期間が3日間も短くなってしまいます。

ということで、開発者としてユーザーからの問い合わせへの返答にも、ユーザーとして無料トライアルを最大限活用するのにも使える豆知識でした。

和暦と改元とうるう年が組み合わさったバグの思い出

あけましておめでとうございます。新年一発目の投稿は2019年の思い出です。

ということで本年もよろしくお願いします 🙏

2019年のSwiftモック事情

こんにちは、id:ikesyoです。これは はてなエンジニア Advent Calendar 2019 17日目のエントリーです。


昨日12月16日(月)に行われた 年末だよ Android/iOS Test Night - 2019 にて、『2019年のSwiftモック事情』という発表をしました。

Swiftでテストのためのモックを用意するとなると、リフレクションでめちゃくちゃするということができないので、素朴に手で書くか、コード生成をすることになります。今回の発表ではコード生成に主眼を置き、以下の4つの選択肢を紹介しました。

それぞれの機能や違いなど詳しい内容は、ぜひ発表のスライドを見てみてください。

Swiftでのモック事情については、今年4月の Mobile Act KYOTO #1 でも発表をしていました。

しかしこの後の8ヶ月で意外と状況が変わっており、その差分を今回の発表に入れ込んでいます。

  • SwiftyMockyの設定ファイルとコマンドが変わった
    • Before: 設定ファイルはmocky.yml、コマンドはsourceryを直接利用
    • After: 設定ファイルはMockfile、コマンドはswiftymockyという専用のものが用意された(Sourceryの存在をラップ・隠蔽)
  • Cuckooの機能追加
  • Mockoloの発表とリリース
    • Uber製のモックジェネレーターで、コード生成が高速であるのが売り
    • 5月に開催されたUIKonf 2019での発表で公表され、OSSとしてリリース予定とされていた
    • 9月に1.0.0がリリースされた

Mockoloについては、UIKonfのセッション動画が公開されており、開発者自ら独自のジェネレーターを作るに至った背景や、高速化のためにやったことを丁寧に説明してくれています。こちらもぜひ見ましょう!

ということで、2019年末時点でのSwiftのモック事情をご紹介しました。どのツールを使うかは、

  • 機能
  • APIの好み
  • チームメンバーの規模や習熟度
  • プロジェクト(コードベース)の規模

など複数の要素に影響されると思います。ぜひ自分たちに適した選択肢を導入してみて、Swiftのテストライフを豊かなものにしていきましょう! 🤖


あわせて読みたい