RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-06-03中級

Rork製iOSアプリにAdMobメディエーションを足したらビルドが通らない — リンカエラーと広告非表示の切り分け

RorkやExpoで作ったiOSアプリにAdMobのメディエーションアダプタ(Unity Ads・Liftoff・InMobi)を追加した途端、ld のリンカエラーやSKAdNetwork不足で広告が出なくなる。症状別に原因を切り分けて解決する手順をまとめました。

AdMob70メディエーション10iOS108ビルドエラー8troubleshooting25SKAdNetwork3CocoaPods3

AdMobのeCPMを少し底上げしようと、メディエーションのアダプタを3つまとめて追加した日のことです。私が運営している iOS 4本(綺麗な壁紙・浮世絵壁紙・Relaxing Healing・Law of Attraction Everyday、いわゆる RWD-iOS グループ)に Unity Ads・Liftoff・InMobi のアダプタを入れたところ、それまで普通に通っていたビルドが ld: framework not found で一斉に落ちました。AdMob 本体のSDKは何も触っていないのに、です。

メディエーションは「アダプタを追加するだけ」と説明されることが多いのですが、実際にはリンク段階と Info.plist の両方に手を入れないと、ビルドが通らない・通っても広告がフィルしない、という二段構えの罠が待っています。同じところで止まっている方のために、症状別の切り分けをまとめておきます。

まず症状を3つに分けて考える

メディエーションアダプタ追加後のトラブルは、見た目が似ていても原因の層が違います。最初にどの症状かを確定させると、無駄な試行錯誤を減らせます。

  • 症状A: ビルドがリンカエラーで落ちるld: framework not found GoogleMobileAdsMediation...Undefined symbols for architecture arm64、あるいは duplicate symbol が出る
  • 症状B: ビルドは通るが、メディエーション広告が一切フィルしない — AdMob 管理画面のメディエーションレポートで該当ネットワークの広告リクエストが0、またはエラー率100%
  • 症状C: ビルドも表示も通るが、計測(収益・アトリビューション)が合わない — SKAdNetwork のポストバックが届かず、ネットワーク側ダッシュボードの数字が極端に低い

AはリンクとPodの整合性、BとCは Info.plist と初期化順序の問題であることがほとんどです。順番に潰していきます。

症状A: リンカエラーの原因はバージョンの不一致

framework not foundUndefined symbols が出る場合、9割はアダプタと AdMob 本体(Google-Mobile-Ads-SDK)のバージョン組み合わせが噛み合っていません。各アダプタは「対応する AdMob SDK のレンジ」を持っていて、ここがずれると、アダプタが期待するシンボルが本体側に存在せずリンクが失敗します。

まず Podfile で、本体とアダプタのバージョンを明示的に揃えます。~> で緩く指定して pod update 任せにすると、アダプタだけ新しい版に飛んで不整合が起きやすいので、私は数字を固定する書き方を好みます。

# Podfile — AdMob 本体とメディエーションアダプタは版を固定して整合させる
target 'YourApp' do
  use_frameworks! :linkage => :static
 
  # AdMob 本体(アダプタが対応するレンジに合わせる)
  pod 'Google-Mobile-Ads-SDK', '12.4.0'
 
  # メディエーションアダプタ(本体 12.x に対応する版を選ぶ)
  pod 'GoogleMobileAdsMediationUnity'
  pod 'GoogleMobileAdsMediationVungle'   # Liftoff は内部的に Vungle アダプタ名
  pod 'GoogleMobileAdsMediationInMobi'
end

ここで :linkage => :static を付けているのがポイントです。Firebase を SPM に移し、AdMob 周りだけ CocoaPods に残すハイブリッド構成にしていると、動的フレームワークと静的ライブラリが混在して duplicate symbol を引き起こすことがあります。広告系アダプタは静的リンクで揃えると、この衝突がほぼ消えます。

Podfile を直したら、中途半端なキャッシュを残さないようにクリーンに入れ直します。

# 古い Pods とロックを捨ててから入れ直す(部分更新で壊れた状態を引きずらない)
rm -rf Pods Podfile.lock
pod deintegrate
pod install --repo-update
 
# Xcode 側のビルドキャッシュも消す(残っていると framework not found が再発する)
rm -rf ~/Library/Developer/Xcode/DerivedData/*

それでも Undefined symbols が消えない場合は、アダプタ単体ではなく、そのアダプタが必要とする SDK 本体(例: InMobiSDK)が入っていないケースを疑います。pod install のログに Installing ... として本体SDKが現れているかを確認してください。アダプタは「橋渡し」であって、ネットワーク本体のSDKは別 Pod として入る必要があります。

症状B: ビルドは通るのに広告が出ないのは Info.plist が原因

リンクが通った後に多いのが「メディエーション広告が一切返ってこない」症状です。AdMob のメディエーションレポートで、追加したネットワークだけリクエスト0が続くなら、Info.plistSKAdNetworkItems が足りていない可能性が高いです。

iOS では、各広告ネットワークの SKAdNetwork ID を Info.plist に列挙しておかないと、そのネットワークの広告配信・計測が成立しません。アダプタを追加しても、この ID は自動では入りません。

<!-- Info.plist — 追加したネットワークぶんの SKAdNetwork ID を列挙する -->
<key>SKAdNetworkItems</key>
<array>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cstr6suwn9.skadnetwork</string> <!-- Google AdMob -->
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4dzt52r2t5.skadnetwork</string> <!-- Unity Ads -->
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>gta9lk7p23.skadnetwork</string> <!-- Vungle / Liftoff -->
  </dict>
</array>

各ネットワークの正確な ID は、必ず公式の最新リストから取得してください(ID は増減します)。私は追加したネットワークの分だけ手で足すより、Google が配布しているメディエーション用のまとめリストをベースに、使っているネットワークだけ残す形にしています。Expo 管理下のプロジェクトなら、Info.plist を直接編集せず app.config.jsios.infoPlist に書くと、prebuild で消えずに残ります。

// app.config.js — Expo prebuild で SKAdNetworkItems が消えないようにする
export default {
  ios: {
    infoPlist: {
      SKAdNetworkItems: [
        { SKAdNetworkIdentifier: 'cstr6suwn9.skadnetwork' },
        { SKAdNetworkIdentifier: '4dzt52r2t5.skadnetwork' },
        { SKAdNetworkIdentifier: 'gta9lk7p23.skadnetwork' },
      ],
    },
  },
};

症状C: 初期化順序とATTで計測が崩れる

ビルドも表示も通っているのに、ネットワーク側の収益が実態より極端に低い場合は、ATT(App Tracking Transparency)のプロンプトと広告SDK初期化の順序を疑います。requestTrackingAuthorization を呼ぶ前に MobileAds を初期化してしまうと、初期化時点では非許諾扱いになり、一部ネットワークが計測精度の低いリクエストを送り続けます。

順序としては、アプリ起動直後に ATT の許諾を取り、その応答を受けてから広告SDKを初期化します。

// 起動直後: ATT の応答を待ってから MobileAds を初期化する
import AppTrackingTransparency
import GoogleMobileAds
 
func initializeAdsAfterATT() {
    ATTrackingManager.requestTrackingAuthorization { _ in
        // 許諾・非許諾どちらでも、応答が確定してから初期化する
        DispatchQueue.main.async {
            MobileAds.shared.start(completionHandler: nil)
        }
    }
}

ここで「許諾が取れなかったら初期化しない」とはしない点に注意してください。非許諾でも広告は出ます。あくまで「ATTの応答が確定してから初期化する」のが目的です。React Native 側で広告を制御している場合も、ネイティブの起動シーケンスでこの順序を守れているかを AppDelegate 周辺で確認します。

予防策: アダプタは一度に1つずつ足す

今回いちばんの反省は、3つのアダプタを一度に入れてしまったことです。リンカエラーが出たとき、どのアダプタが原因かを特定するのに余計な時間がかかりました。累計5,000万ダウンロードのアプリ群を12年運用してきて、収益系の変更ほど「一度に1つ、ビルドが通ることを確認してから次」が結局いちばん速い、と痛感しています。

具体的には、アダプタを1つ追加 → クリーンビルドが通ることを確認 → 実機でテスト広告がフィルすることを確認 → AdMob 管理画面でリクエストが立つことを確認、までを1ネットワークぶん完了させてから次に進みます。SKAdNetworkItems も同じタイミングで1ネットワークずつ足すと、計測が崩れたときに原因を絞れます。

もう一点、テスト時は必ず AdMob のテストデバイスID を登録してテスト広告で確認してください。本番広告でクリックを繰り返すとポリシー違反になり、せっかくの設定が無駄になります。

参考リンク

メディエーションは設定が通ってしまえば手離れの良い仕組みですが、最初の導入だけは層がいくつも重なっていて詰まりやすい部分です。同じところで止まっている方の切り分けの一助になれば嬉しいです。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-05-03
Rork書き出しiOSプロジェクトの「pod install」が止まる — Apple Silicon時代の現実的な直し方
Rorkで生成したiOSプロジェクトのpod installが失敗する原因を、Apple Silicon Mac特有のRubyアーキテクチャ問題、CocoaPodsバージョン競合、Hermes/Folly関連の落とし穴まで具体的に解説します。
開発ツール2026-06-02
広告の本当のeCPMを自分で測る — Impression-Level Ad Revenue を計測基盤に流し込む実装記録
AdMob の管理画面が見せる平均eCPMだけでは、どの地域やプレースメントが本当に稼いでいるかは分かりません。1インプレッションごとの収益を paidEventListener で受け取り、解析基盤に流して本当のeCPMを出すまでの実装と運用をまとめました。
開発ツール2026-05-26
iOSのフォアグラウンド通知が表示されない — expo-notifications のハマりどころと対処
iOS実機でアプリが前面にあるときだけプッシュ通知が表示されない問題を、expo-notifications の setNotificationHandler の正しい書き方と iOS 14 以降の表示プロパティの違いから整理します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →