Admobのネイティブアドバンス広告を試してみる
Admobのネイティブアドバンス広告というフォーマットを試してみました。
これは他社でよくあるネイティブ同様、渡された文字列や画像で広告画面を作っていくもののようです。
ネイティブアドバンス広の広告ユニット作成
まずはAdmobの画面から広告ユニットを作成します。
下のネイティブを選択して、「ネイティブ広告アドバンスに切り替える」リンクをクリックします。
注) こちらのリンクですが、2017/10/23現在アカウントによって出たり出なかったりしているようです。
もしかすると一部ユーザーにしか開放されていないのかもしれません。
切り替えたら広告の種類を選んで作成完了です。
ネイティブアドバンス広告の実装
まずはCocoaPodsでAdmobをインストールします。
target 'MyApp' do use_frameworks! pod 'Google-Mobile-Ads-SDK' end
ネイティブアドバンス広告のデータ取得は下の通りです。
adUnitIDは先程登録したものを利用してください。
import UIKit import GoogleMobileAds class ViewController: UIViewController { var adLoader: GADAdLoader? override func viewDidLoad() { super.viewDidLoad() adLoader = GADAdLoader(adUnitID: "AD UNIT ID", rootViewController: self, adTypes: [.nativeAppInstall], options: nil) adLoader?.delegate = self adLoader?.load(GADRequest()) } } extension ViewController: GADNativeAppInstallAdLoaderDelegate { func adLoader(_ adLoader: GADAdLoader, didReceive nativeAppInstallAd: GADNativeAppInstallAd) { } func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) { } }
Delegateメソッドでは、広告のタイトル・アイコン・本文などが渡されるので、それを使って広告を組み立てます。
extension ViewController: GADNativeAppInstallAdLoaderDelegate { func adLoader(_ adLoader: GADAdLoader, didReceive nativeAppInstallAd: GADNativeAppInstallAd) { nativeAppInstallAd.headline // → タイトル nativeAppInstallAd.body // → 説明文 } func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) { } }
実際の広告表示はXibファイルを利用します。
Xibファイルを作り、そのViewをGADNativeAppInstallAdViewにします。
その上にラベルを配置して、GADNativeAppInstallAdViewのheadlineViewなど、各プロパティーに紐付けていきます。
ここまで終わったら、Xibを使って広告を表示します。
下では、Xibを読み込んでheadlineとcallToActionをセットしています。
extension ViewController: GADNativeAppInstallAdLoaderDelegate { func adLoader(_ adLoader: GADAdLoader, didReceive nativeAppInstallAd: GADNativeAppInstallAd) { let adView = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! GADNativeAppInstallAdView adView.backgroundColor = UIColor.lightGray adView.frame = CGRect(x: 0, y: view.frame.height - 50, width: view.frame.width, height: 50) adView.nativeAppInstallAd = nativeAppInstallAd view.addSubview(adView) (adView.headlineView as? UILabel)?.text = nativeAppInstallAd.headline (adView.callToActionView as? UILabel)?.text = nativeAppInstallAd.callToAction } func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) { } }
実行すると広告を表示する事ができます。
ラベルをタップすればAppStoreのページに遷移します。
今回は試してないのですが、広告タイプはインストール型以外にもあるようです。
GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeNativeAppInstall; GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeNativeContent; GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeNativeCustomTemplate; GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeDFPBanner;
iPhoneアプリリリース時の「輸出コンプライアンス」のチェックを省く方法
iTunesConnectから審査に提出する際、「輸出コンプライアンス」と「広告ID」についてチェックをする必要があります。
毎回入力するのが手間だったので、省略する方法はないか調べてみました。
調べたところ、「輸出コンプライアンス」はInfo.plistにITSAppUsesNonExemptEncryptionを入れれば省略できるようです。
試したところ「輸出コンプライアンス」が表示されなくなりました。
objc_getAssociatedObjectで既存オブジェクトにプロパティーを追加
objc_getAssociatedObjectを使ってUIViewに新しいプロパティーを生やしてみました。
UIViewにプロパティーを追加する
UIViewにvalueというプロパティーを生やします。
実装は簡単で、下のようなextensionを追加すれば完了です。
private var valueKey = 0 extension UIView { var value: Int? { get { return objc_getAssociatedObject(self, &valueKey) as? Int } set { objc_setAssociatedObject(self, &valueKey, newValue, .OBJC_ASSOCIATION_ASSIGN) } } }
実行すると、下のように値をセットする事ができます。
let view = UIView() print(view.value) // → nil view.value = 10 print(view.value) // → Optional(10)
もちろんインスタンスが違えばプロパティーも別です。
let view = UIView() let view2 = UIView() view.value = 10 print(view.value) // → Optional(10) print(view2.value) // → nil
キーとして宣言したvalueKeyですが、型はInt以外でも問題ありません。
private var valueKey = "valueKey" extension UIView { var value: Int? { get { return objc_getAssociatedObject(self, &valueKey) as? Int } set { objc_setAssociatedObject(self, &valueKey, newValue, .OBJC_ASSOCIATION_ASSIGN) } } }
valueKeyの値は他プロパティーと被っても問題ありません。
private var valueKey = "valueKey" private var valueKey2 = "valueKey" extension UIView { var value: Int? { get { return objc_getAssociatedObject(self, &valueKey) as? Int } set { objc_setAssociatedObject(self, &valueKey, newValue, .OBJC_ASSOCIATION_ASSIGN) } } var value2: Int? { get { return objc_getAssociatedObject(self, &valueKey2) as? Int } set { objc_setAssociatedObject(self, &valueKey2, newValue, .OBJC_ASSOCIATION_ASSIGN) } } } let view = UIView() print(view.value) // → nil print(view.value2) // → nil view.value = 10 print(view.value) // → Optional(10) print(view.value2) // → nil
UICollectionViewの並び替え
UICollectionViewでの並び替えを試してみました。
Storyboardを使わないでUICollectionViewを表示
まずは普通にUICollectionViewを表示してみます。
コードは下の通りです。
class CollectionViewController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell") collectionView?.backgroundColor = UIColor.white } override func numberOfSections(in collectionView: UICollectionView) -> Int { return 2 } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 5 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) cell.backgroundColor = UIColor.lightGray return cell } }
CollectionViewのレイアウトは下の通りです。
let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: 100, height: 100) layout.minimumLineSpacing = 10 layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
実行すると下のようにCollectionViewが表示されます。
UICollectionViewの並び替え
UICollectionViewの並び替えはmoveItemAtを実装するだけで完了です。
class CollectionViewController: UICollectionViewController { override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { } }
これで下のように並び替えをする事ができるようになります。
【Xcode】Debug Memory Graphでメモリリークをチェック
Xcode8から登場したDebug Memory Graphという機能を試してみました。
これはインスタンス間の参照を図として表示できるもので、循環参照の発見などに役立ちます。
Debug Memory Graphは、アプリ起動後にデバッグエリア右端のアイコンをタップする事で実行できます(下画像の右端)
アイコンをタップすると、下のようにアプリ上のインスタンス一覧が表示されます。
インスタンスを選択すると、下のようにインスタンス同士の参照を図として見る事ができます。
次に、下のように循環参照する処理を書くとどうなるか試してみました。
class MyClassA { var myClass: MyClassB? } class MyClassB { var myClass: MyClassA? } let myClassA = MyClassA() let myClassB = MyClassB() myClassA.myClass = myClassB myClassB.myClass = myClassA
Debug Memory Graphで見ると、下のように相互に参照をもっている事が分かります。
インスタンス一覧には紫色の警告マークが出るので、循環参照がすぐに分かります。
循環参照がない場合は下のように一方向だけの矢印になります。
【Swift】mp3をバックグラウンド再生する
バックグラウンド再生を試してみました。
mp3をフォアグラウンドで再生
まずはフォアグラウンドでmp3を再生してみます。
再生したいmp3ファイルをAssets.xcassetsに追加して下さい。
そのあと下のようにmp3再生処理を記述すれば完了です。
import UIKit import AVFoundation class ViewController: UIViewController { var player: AVAudioPlayer? override func viewDidLoad() { if let sound = NSDataAsset(name: "bgm") { player = try? AVAudioPlayer(data: sound.data) player?.play() // → これで音が鳴る } } }
mp3をバックグラウンドで再生
次はアプリをバックグラウンドにしても再生し続ける方法を試します。
まずはCapabilitiesのBackground ModesをONにして、Audio Airplay and Picture in Pictureにチェックを入れます。
その後、AppDelegateなどに下2行を追加すれば完了です。
try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers) try? AVAudioSession.sharedInstance().setActive(true)
import UIKit import AVFoundation @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers) try? AVAudioSession.sharedInstance().setActive(true) return true } }
これでアプリがバックグラウンドに移動してもbgmが再生されます。
シミュレータでは上の処理を追加してもバックグラウンド再生されないので注意が必要です。
【iOS】1つの画像データで2xと3xにも対応する
毎回2xと3xのデータを作るのが大変だったので、1つの画像データ(PDF形式)で全部に対応する方法を調査しました。
今回は下のような画像で検証しました。
利用したツールはSketchです。
まずはこのデータをpdfとして書き出します。
次にAssets.xcassetsでImage Setを作成します。
今作ったImage SetのScaleをSingle Scaleに変更します。
変更したら先程作ったPDFをドラッグ&ドロップで追加します。
登録したPDFは、普通の画像と同じように利用する事ができます。
アプリを起動すると、画像が正常に表示されている事が分かります。
下はPDFの代わりにpngを使った画像です。
PDFでないと画像がぼやける事が分かります。