要約:iOSアプリでstatというグローバル変数を定義したらAdmobでコケた
本文
iOSでのゲーム作りはしたことがなかったのだけど、How To Create A Simple 2D iPhone Game with OpenGL ES 2.0 and GLKit - Part 1 | Ray Wenderlichを読みながら進めてみた。結構簡単にできちゃう。ES2.0はiPhone4以降でサポートされ、iPhone3Gなどでは動かないらしいので、別途対応した方がいいのかもしれないが、まあそれは別の話。
作ったアプリにAdmobを組み込もうとしたところ、大いに手こずった。iOSへのAdmobの組み込みは、Google DevelopersのGoogle AdMob Ads iOS(初級) - Google Mobile Ads SDK — Google Developersで、OpenGL ESじゃない普通のUIViewControllerのアプリで確認済み(ただこのドキュメントの通りでは動かなくて、AdSupportとStoreKitというframeworkも組み込んで、Other Linker Flagsに-ObjCを追加する必要がある)。
まずXcodeでプロジェクトを作るときに、上記のページのようにEmpty Applicationテンプレートから作ったプロジェクトだとGADBannerView
が表示されないという現象が起こった。setDelegate
でadViewDidReceiveAd
は受け取っているので、読み込み自体はできてるんだけど表示されなくて、これは結局原因が分からなかった。
GLKViewController
を使ったアプリにAdmobを組み込めないのかと思ったが、プロジェクトをEmpty Applicationからじゃなくて、OpenGL Gameテンプレートから作ると表示されることがわかった。原因は不明。
で自分のアプリに組み込んでいったところ、GADBannerView
のloadRequest
を呼び出すとEXC_BAD_ACCESS
で停止するという現象が出た。エラーの出る位置としては、
[GADCachedFile fileModificationDate] at GADCachedFile.m:86: |
というところで止まる。これが必ず止まる訳ではなくて、Cleanしたら一時的に動くけど、なんか変更するとやっぱり発生する、とかいう謎の状態だった。
原因が分からなくて、ゲームのロジックを全部外して、また一つずつ追加したりしてすったもんだしたあげくようやく原因がわかった。グローバル変数にゲームの状態を示すstat
という変数を使っていたのが問題だった。この変数はenum
の型で宣言していたので、1バイトになってしまってアライメントがずれてうんぬん、かと思って FORCE_DWORD = 0xffffffff
とか無理矢理4バイトにしてみたがダメ。とかあれこれやっていたが、ふとC言語のシステムライブラリにstat
という関数があることを思い出した。同じ名前を使ってしまっていたのでライブラリにあるstat関数はリンクされず、Admobの中からstat
が呼び出されたときに変数領域を実行しようとしてエラーが出ていた、ということだった。
これちょっと発見するの難しいなぁ。そもそもグローバル変数を使わなければいいんだろうけど。