iOS の Google AdMob のテスト広告が出なくなってしまった時の対応

ここに書いてある「デモ広告」のユニット ID を使って、テスト広告を表示させていたのだが、いつの間にか出なくなっていた。

実行時にこんなログが出る。

<Google> Cannot find an ad network adapter with the name(s): com.google.DummyAdapter. Remember to link all required ad network adapters and SDKs, and set -ObjC in the 'Other Linker Flags' setting of your build target.

ドキュメントをよく見たら

注意:アプリで app-ads.txt ファイルを設定している場合は、デモ広告ユニットを使って広告を読み込むために、次の行を app-ads.txt ファイルに含める必要があります。

と記載があったので、 app-ads.txt にコードを追加する。

... 既存の記載 ...
google.com, pub-3940256099942544, DIRECT, f08c47fec0942fa0

そうして数時間経ったら、前のように「デモ広告」が表示されるようになった。 以前はドキュメントにデモ用の app-ads.txt の記載あったかなぁ・・・

ちなみに、↑とは別に「テストデバイス」設定をする方法でも、デモ広告は表示される。

SwiftUI で下から出てくる Picker を作ってみる

UIKit の場合だと UITextField の inputView に UIPicker を設定して、UITextField をタッチすると下からニュッと Picker が出てくる。ができる。

それを SwiftUI でやろうとすると、適当なものが用意されていなかったので、作ってみた。

こんな感じ。

コードは GitHub にあります。

Xcode プロジェクトにローカルの SwiftPackage を追加する

SwiftPackageManager で配布されているパッケージを、ローカルに持ってきてそれを Xcode プロジェクトで参照して使用するメモ。

  1. パッケージのリポジトリを clone する。
  2. 対象のアプリのプロジェクトを開く
  3. Xcode のプロジェクトツリーに、パッケージのフォルダ(Package.swift があるフォルダ)をドラッグ&ドロップする。
  4. ターゲットの Link Binary With Libraries を開く
    • 追加の + ボタンをクリックする。
      • f:id:daisuke-t-jp:20210427214547p:plain:h500
    • 対象の Package を選び、追加する。
      • f:id:daisuke-t-jp:20210427214838p:plain:h500
  5. import できるようになっているので、ビルドする。

ローカルで参照したこの状態では Xcode 上でパッケージのコード編集してビルドすると、変更したパッケージの動作を試せるので、パッケージの挙動を試したり、修正することができる。

写真に写っている人・動物をヒエログリフにする iOS アプリを作ってみた

機械学習フレームワークを使ったアプリを作ってみたくなり、試しに作ってみた。ついでに最近、エジプトのヒエログリフが面白いなあ、と思っていたのでそれをアプリのテーマにした。

Egyptian Hieroglyphs Photo

Egyptian Hieroglyphs Photo

  • Daisuke Tonosaki
  • 写真/ビデオ
  • 無料

Apple の review に提出する際に、かなり機能が単純なアプリだからリジェクトされるかと思ったが、大丈夫だった。
(審査にデモビデオは添付した)

アプリを使って変換すると、こんな感じで写真 → エジプトのヒエログリフの壁画風の画像になる。

f:id:daisuke-t-jp:20210303213230p:plain:w500

f:id:daisuke-t-jp:20210303213422p:plain:h400 f:id:daisuke-t-jp:20210303213440p:plain:h400

アプリの動作はこんな感じ。

www.youtube.com

精度はそんなに良くなく、たとえば写真全体に人や動物が大きく写っていると、残念ながらうまくいかない。。


ざっくりとした処理の流れは↓の感じ。

  1. あらかじめ、使用するヒエログリフの画像を作成して用意しておく
  2. 写真から人や動物を認識する
  3. 認識した領域にもっとも特徴が近いヒエログリフを探し、該当するヒエログリフで写真を置き換える

やってみて悩ましかった点は

多数の画像(ヒエログリフ)から VNFeaturePrintObservation を作ると時間がかかりすぎる。アプリの利用上の障害がある、という問題があった。

解決策としては

  • 実行時に特徴検出を逐次作成するのではなく
  • あらかじめ、各画像の VNFeaturePrintObservation を作成しておいてそれを CoreData で DB に保存しておく
    • そしてそれをアプリにバンドルしておく
  • アプリの実行時には作っておいた DB からVNFeaturePrintObservation を fetch する

という形にした。

VNFeaturePrintObservation の継承元の VNObservationNSSecureCoding を採用しているので、CoreData の Attribute の型を Transformable にして、下のようなカスタムの Transformer クラスを使用することで CoreData に保存できる。

@objc(VNFeaturePrintObservationTransformer)
class VNFeaturePrintObservationTransformer: NSSecureUnarchiveFromDataTransformer {
    static let name = NSValueTransformerName(rawValue: String(describing: VNFeaturePrintObservationTransformer.self))
    
    override class var allowedTopLevelClasses: [AnyClass] {
        return super.allowedTopLevelClasses + [VNFeaturePrintObservation.self]
    }
    
    public static func register() {
        let transformer = VNFeaturePrintObservationTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}

Google ML Kit や Core ML はほとんど触ったことがなく難しい印象だったが、やってみると楽しかった。

iOS の Google MLKit で静止画像の ObjectDetection を試してみた

Google MLKit の ObjectDetection での静止画像の解析を試してみた。

公式のサンプルもあるが、バンドルされている静止画像しか解析できない。

そのため、写真を選んで解析する iOS サンプル を作ってみた。

動かすとこんな感じ。

試してみて分かったこと

  • Firebase のセットアップをしなくても使える
    • Google MLKit はもともとは Firebase MLKit という名前だったが
    • Firebase ではなくなり、Firebase のセットアップ(GoogleService-Info.plist の追加など)をしなくても最低限使えるようになったため、とっつきやすい。
  • 認識できるオブジェクトの最大数は 5 である
  • TensorFlowLite と比べると
    • TensorFlowLite ではモデルの用意が必要になるが、Google MLKit ではモデルを用意しなくても、標準でバンドルされているベースモデルを使ってくれるため、とりあえず簡単に解析をしてみたい場合は、Google MLKit を使うと良い。
  • ベースモデル以外にカスタムモデルも使用可能
    • カスタマイズされたモデルを使うことも可能なので、拡張性もある。
    • カスタマイズモデルの取り込み方法は、以下がある。
      • ローカルファイルから読み込む
      • Firebase でホスティングされているモデルを読み込む

CocoaPods で「Your project does not explicitly specify the CocoaPods master specs repo...」の警告が出る

pod のコマンドを実行した時、以下の警告が表示されるようになった。

[!] Your project does not explicitly specify the CocoaPods master specs repo.
Since CDN is now used as the default, you may safely remove it from your repos directory via `pod repo remove master`.
To suppress this warning please add `warn_for_unused_master_specs_repo => false` to your Podfile.

警告メッセージのとおりpod repo remove master をするが

% pod repo remove master
[!] repo master does not exist

master リポジトリがない、と返される。

なので、もうひとつメッセージに書いてある warn_for_unused_master_specs_repo => false を Podfile に追加する。

platform :ios, '14.0'
use_frameworks!

install! 'cocoapods',
            :warn_for_unused_master_specs_repo => false

target 'App' do
# ...
end

これで警告メッセージが出なくなる。

現時点でドキュメントに見当たらなかったが warn_for_unused_master_specs_repoinstall! のオプションに指定するみたい。

https://github.com/CocoaPods/CocoaPods/blob/3593ac03a661fbdd7479a648062a42065d34412c/lib/cocoapods/installer/installation_options.rb#L159


↑の警告と同時に、以下のメッセージが pod コマンド実行時に表示されていた。

Ignoring ffi-1.13.1 because its extensions are not built. Try: gem pristine ffi --version 1.13.1

私の場合 brew で cocoapods をインストールしていたので、試しに

% brew upgrade

をしたら、以後表示されなくなった。

Apple Archive フレームワークを使って LZFSE の CLI ツールを作った

macOS 11.0(Big Sur)、iOS 14 から Apple Archive Framework が使えるようになった。

Apple Archive Framework

Apple Archive Framework では Apple によって開発された LZFSE アルゴリズムの圧縮・展開ができる。

LZFSE

試しにこの Apple Archive Framework を使って LZFSE の展開・圧縮の CLI ツールを作ってみた。
(Big Sur 標準の aa コマンドで LZFSE の圧縮・展開ができるが、それのミニバージョンという感じ。)

ツールの使い方は

これでファイルを圧縮できる。(.lzfse ファイルができる)

$ ./lzfse-cli --encode -i alice29.txt

ファイルの展開。

$ ./lzfse-cli --decode -i alice29.txt.lzfse

フォルダの圧縮もできる。(.aar ができる)

$ ./lzfse-cli --encode -i dir

フォルダの展開。

$ ./lzfse-cli --decode -i dir.aar

CLI ツールを作るにあたって、コマンドの引数解析には Swift Argument Parser を使ってみた。

引数パラメータ解析や、エラー処理を独自に実装しなくて良いし、オプション引数も簡単に扱えるので、非常に良い。