SpriteKitで作ったアプリにAdmobを実装する
環境
主なファイル構成
- GameViewController
- GameScene.swift
Admobの登録
- 省略
SDKのインストール
source 'http://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! pod 'Google-Mobile-Ads-SDK' target 'プロジェクト名' do end
ビルドするとBitcodeのエラーが出た
- エラー内容
GoogleMobileAds.framework/GoogleMobileAds(GADDefaultInAppPurchaseFlow.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
- Bitcodeを無効にして対応(参考)
- TARGETS > プロジェクト名 > Build Setting > Build Options > Enable Bitcode を「No」に変更した (最初、表示をBasicにしていて検索しても出てこなかった)
(Bitcodeって?)
フレームワークの追加
- TARGETS > プロジェクト名 > General > Linked Frameworks and Libraries から必要なフレームワークを追加
必要なフレームワーク
- AdSupport
- AudioToolbox
- AVFoundation
- CoreGraphics
- CoreMedia
- CoreTelephony
- EventKit
- EventKitUI
- MessageUI
- StoreKit
- SystemConfiguration
バナー広告の追加
- ここにはStoryboardを利用したやり方しかのっていなかったので、こちらを参考にさせてもらい作業をすすめる
- GameViewController.swiftに参考記事のコードを記述したら表示された (以下を
viewDidLoad
から呼び出す)
func showAd() { let banner:GADBannerView = GADBannerView(adSize: kGADAdSizeSmartBannerPortrait) banner.adUnitID = "ca-app-pub-xxxxxxxxxxxxxxxxxxxxxxxx" banner.delegate = self banner.rootViewController = self let gadRequest:GADRequest = GADRequest() banner.loadRequest(gadRequest) self.view.addSubview(banner) }
- GameScene.swift上でバナーの表示非表示をコントロールしたかったので、
var banner: GADBannerView!
をグローバル変数とし、banner.hidden = true/false
でコントロールした
インタースティシャル広告の追加
- バナー同様、こちらの記事を参考にさせてもらい実装した
- バナーと同様の理由でグローバル変数で宣言した
- インタースティシャルは使い捨てオブジェクトとのことだったので、
interstitialDidDismissScreen
にて新しいインスタンスを作るようにした
var interstitialAD: GADInterstitial! //interstitialという名前は使えなかった class GameViewController: UIViewController, GADBannerViewDelegate, GADInterstitialDelegate { override func viewDidLoad() { super.viewDidLoad() interstitialAD = createAndLoadInterstitial() } func createAndLoadInterstitial()->GADInterstitial { let interstitial = GADInterstitial(adUnitID: "ca-app-pub-xxxxxxxxxxxxxxxxxxxxxx") interstitial?.delegate = self let gadRequest:GADRequest = GADRequest() interstitial?.loadRequest(gadRequest) return interstitial! } func interstitialDidDismissScreen(ad: GADInterstitial!) { interstitialAD = createAndLoadInterstitial() } }
- 広告の呼び出しは、こちらを参考にさせていただき、以下のように行っている
func showInterstitial() { let currentViewController: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController! interstitialAD?.presentFromRootViewController(currentViewController) }
Nifty Mobile Backendでプッシュ通知を実装してみた(Swift)
環境
- Xcode: 7.1.1
- NCMB: 2.2.3
背景
プッシュ通知にはfelloのサービスを利用していたが、Xcode7になってから実装方法がわからなくなってしまったのと、mBaaSに興味があったのでmobile backendの実装を試すことにした。
証明書準備
公式のチュートリアルがわかりやすく、そのまま進めたら準備が完了した。felloの場合、pemの作成が必要だったので、その手間がないのは楽だった。(pem作成自体は、ドキュメント通りすすめれば難しいことはないが)
SDKインストール
クイックスタートをみて、CocoaPodsでSDKをインストールするも、その後の説明がObjective-Cでの例しか見つからなかった。検索してみるとSwiftを用いた記事があったので、こちらを参考にする。記事内にも説明があるが、CocoaPodsからのインストールだとエラーが出てしまったので、GitHubからSDKをダウンロードしてインストールした。(SDKのダウンロードはこちら参考にした。)
実装
Bridging-Header.hの追加
こちらの記事を参考にBridgingHeaderを追加した。Build Settings > Objective-C Bridging Headerには$(SRCROOT)/$(PRODUCT_NAME)/$(PRODUCT_NAME)-Bridging-Header.h
と指定してみた。$(PRODUCT_NAME)-Bridging-Header.hの中身は以下の通り。
// for Nifty Mobile Backend #import "NCMB/NCMB.h"
AppDelegate.swiftの更新
Swiftでの記述が調べられなかったが、こちらの記事通りに進めたら実装が完了しプッシュ通知が確認できた。
エラー(ワーニングだったかな?)対応
You've implemented -[ application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need to add "remote-notification" to the list of your supported UIBackgroundModes in your Info.plist.
といったエラーが出たので、こちらの記事を参考にTARGETS > Capabilities > Background Modes をオンにして、Remote notificationsにチェックを入れた。念のためPush Notificationsもオンにした。エラーも出なくなり、プッシュ通知の受け取りに成功した。
開封通知(正常に実装できていなそう)
プッシュ通知の開封通知の記述を追加しようとドキュメントを見るも、やはりObjective-Cでの説明のため、変換サービスなどを利用し、以下のように記述してみた。アプリ起動時の通知は取得できたが、アプリ終了時での開封通知が取得できない場合がある。どこか実装をミスっていそう。
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // 省略 NCMB.setApplicationKey(Const.NcmbApplicationKey, clientKey: Const.NcmbClientKey) // 以下の行を追加 NCMBAnalytics.trackAppOpenedWithLaunchOptions(launchOptions) // 省略 } func application(application: UIApplication, didReceiveRemoteNotification userInfo:[NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void){ // 以下の行を追加 if application.applicationState == .Active { NCMBAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo) } }
バッジ表示のコントロール
このままだとバッジが消えないので、AppDelegate.swiftにバッジをクリアする処理を入れた。Felloの時のものをそのままだが以下の通り記述した。
func applicationWillEnterForeground(application: UIApplication) { UIApplication.sharedApplication().applicationIconBadgeNumber = -1 }
アプリ起動時にバッジを消すことは可能になったが、mobile backendにはバッジ件数に「インクリメントする」といった設定がある。こちらのissueを見ると「開封通知登録APIを実行する」ことで「データストア上の端末情報にあるバッジ数のみリセット」となっている。前述通り、開封通知の部分が正常に実装できていなそうなので、こちらの機能は使えていない。(数字がクリアされない。)
iOS7対応(保留)
このままで対応OSをiOS7とするとUIUserNotificationSettings
がiOS7に対応していないためエラーが出てしまう。公式ドキュメントでは以下のように説明がある。
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1){ //iOS8以上での、DeviceToken要求方法 //通知のタイプを設定したsettingを用意 UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound; UIUserNotificationSettings *setting; setting = [UIUserNotificationSettings settingsForTypes:type categories:nil]; //通知のタイプを設定 [[UIApplication sharedApplication] registerUserNotificationSettings:setting]; //DevoceTokenを要求 [[UIApplication sharedApplication] registerForRemoteNotifications]; } else { //iOS8未満での、DeviceToken要求方法 [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; }
こちらを参考に
if #available(iOS 8.0, *) { let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil) application.registerUserNotificationSettings(settings) application.registerForRemoteNotifications() } else { UIApplication.sharedApplication().registerForRemoteNotificationTypes(.Alert | .Badge | .Sound); }
このように記述してみるも、Type of expression is ambiguous without more context
とエラーが出てしまい。実装方法がわからなかった。
結果
- Xcode: 7.1.1
- NCMB: 2.2.3
- iOS8以上は実装完了
- iOS7以下は実装未完了
- 開封通知の挙動が不安定(インクリメントがリセットできない)
WatchKitの画面リロードやインジケータがわからない
環境
- Xcode: 7.1.1
- watchOS: 2
画面リロードはどうやるのか?
WatchKitにて、Memu ItemのタップをきっかけにWKInterfaceLabelを更新するコードを書いてみた。
@IBAction func nextPost() { title.setText("タイトル更新") body.setText("本文更新") }
更新後にスクロール位置を最上段に持って行きたかったのだが、ただsetText
しただけではスクロール位置が変わらなかった。setHidden
で一度WKInterfaceLabelを消してから、再度表示させるようにしたら上段に移動した。
@IBAction func nextPost() { title.setHidden(true) body.setHidden(true) title.setText("タイトル更新") body.setText("本文更新") title.setHidden(false) body.setHidden(false) }
インジケータがない?
上記のようにLabelを消す形にしたら、消えているあいだ画面が真っ黒になるのが気になった。Indicatorが見つからなかったので、消えている間は"Loding..."とLabelを表示するようにした。
@IBAction func nextPost() { title.setHidden(true) body.setHidden(true) loding.setHidden(false) title.setText("タイトル更新") body.setText("本文更新") title.setHidden(false) body.setHidden(false) loding.setHidden(true) }
もっと良い方法はないだろうか。
今日から始めます。
はじめまして。