【SwiftUI】ネイティブ広告の表示方法

第0部: [スタートガイド](https://qiita.com/SNQ-2001/items/44f3446ce0966c78641b)

第1部: [リワード広告](https://qiita.com/SNQ-2001/items/253173abefc6f90f86ea)
第2部: [インタースティシャル広告](https://qiita.com/SNQ-2001/items/5590a55324c39582a9ef)
第3部: [ネイティブ広告](https://qiita.com/SNQ-2001/items/7151fdcb8e9f8c2c42c2) ← イマココ
第4部: [バナー広告](https://qiita.com/SNQ-2001/items/9bf389475cb5995469a0)
第5部: [アプリ起動広告](https://qiita.com/SNQ-2001/items/75ce24982bf418c52349)

# はじめに
AdMob広告シリーズ第3部です
今回は[ネイティブ広告](https://developers.google.com/admob/ios/native/start?hl=ja)です。
見た目的にはバナー広告に近いように思います。
バナー広告と違う点は広告のUIが変更可能という事です。
これによりアプリに馴染ませることができ、UXの向上につながります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/6b0c69d3-d6b5-05d2-d68f-9deb486fcca3.png)

今回は公式から提供されているデモレイアウトを使用してネイティブ広告を実装していこうと思います。

# 実装準備
実装の前に[スタートガイド](https://developers.google.com/admob/ios/quick-start?hl=ja)に記載してある事を行います

①: Mobile Ads SDK のインポート
②: Info.plist の更新
③: Mobile Ads SDK の初期化

[こちら](https://qiita.com/SNQ-2001/items/44f3446ce0966c78641b)で詳しく解説してあります。
これが終われば準備は完了です。

# 実装
[こちら](https://github.com/googleads/googleads-mobile-ios-examples)からAdMob広告サンプルプロジェクトをダウンロードします。
![スクリーンショット 2022-05-12 20.55.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/bd51a9e7-ea9e-442a-7102-d89fd3809a55.png)
ダウンロードしたファイルから`NativeAdView.xid`を探します。
![スクリーンショット 2022-05-12 20.57.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/94d0b462-e86c-50ae-fbcf-4058d8813550.png)
`NativeAdView.xid`をプロジェクト内にドラッグします。
![スクリーンショット 2022-05-12 20.59.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d6f94242-1e00-d7d2-89a2-d1de8f074d27.png)
`Copy item if needed`にチェックを入れてFinishを押します。
![スクリーンショット 2022-05-12 21.00.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/9bcbec2e-eba7-8a0d-8310-71dea3a2dd89.png)

`NativeAdView.xib`をオリジナルUIに変更しましょう
![スクリーンショット 2022-05-12 21.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b93b9463-49b6-c597-6ea5-63769c409c8b.png)

私はこんな感じにアレンジしました。
どんな風になったかは最後にスクショ載せときます。
![スクリーンショット 2022-05-12 22.06.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2d31e597-4459-4269-303f-0d48f39b121d.png)



```Native.swift
import SwiftUI
import GoogleMobileAds

struct NativeView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        let viewController = GADNativeViewController()
        return viewController
    }
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
    }
}

class GADNativeViewController: UIViewController, GADNativeAdDelegate, GADNativeAdLoaderDelegate {
    var heightConstraint: NSLayoutConstraint?
    var adLoader: GADAdLoader!
    var nativeAdView: GADNativeAdView!
    let adUnitID = "ca-app-pub-3940256099942544/3986624511"

    override func viewDidLoad() {
        super.viewDidLoad()

        guard
            let nibObjects = Bundle.main.loadNibNamed("NativeAdView", owner: nil, options: nil),
            let adView = nibObjects.first as? GADNativeAdView
        else {
            return assert(false, "Could not load nib file for adView")
        }
        setAdView(adView)
        refreshAd()
    }

    func setAdView(_ view: GADNativeAdView) {

        nativeAdView = view
        self.view.addSubview(nativeAdView)
        nativeAdView.translatesAutoresizingMaskIntoConstraints = false
        let viewDictionary = ["_nativeAdView": nativeAdView!]
        self.view.addConstraints(
            NSLayoutConstraint.constraints(
                withVisualFormat: "H:|[_nativeAdView]|",
                options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewDictionary)
        )
        self.view.addConstraints(
            NSLayoutConstraint.constraints(
                withVisualFormat: "V:|[_nativeAdView]|",
                options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewDictionary)
        )
    }
    func refreshAd() {
        adLoader = GADAdLoader(
            adUnitID: adUnitID, rootViewController: self,
            adTypes: [.native], options: nil)
        adLoader.delegate = self
        adLoader.load(GADRequest())
    }
    func imageOfStars(from starRating: NSDecimalNumber?) -> UIImage? {
        guard let rating = starRating?.doubleValue else {
            return nil
        }
        if rating >= 5 {
            return UIImage(named: "stars_5")
        } else if rating >= 4.5 {
            return UIImage(named: "stars_4_5")
        } else if rating >= 4 {
            return UIImage(named: "stars_4")
        } else if rating >= 3.5 {
            return UIImage(named: "stars_3_5")
        } else {
            return nil
        }
    }
    func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) {
        nativeAd.delegate = self
        heightConstraint?.isActive = false
        (nativeAdView.headlineView as? UILabel)?.text = nativeAd.headline
        (nativeAdView.bodyView as? UILabel)?.text = nativeAd.body
        nativeAdView.bodyView?.isHidden = nativeAd.body == nil

        (nativeAdView.callToActionView as? UIButton)?.setTitle(nativeAd.callToAction, for: .normal)
        nativeAdView.callToActionView?.isHidden = nativeAd.callToAction == nil

        (nativeAdView.iconView as? UIImageView)?.image = nativeAd.icon?.image
        nativeAdView.iconView?.isHidden = nativeAd.icon == nil

        (nativeAdView.starRatingView as? UIImageView)?.image = imageOfStars(from: nativeAd.starRating)
        nativeAdView.starRatingView?.isHidden = nativeAd.starRating == nil

        (nativeAdView.storeView as? UILabel)?.text = nativeAd.store
        nativeAdView.storeView?.isHidden = nativeAd.store == nil

        (nativeAdView.priceView as? UILabel)?.text = nativeAd.price
        nativeAdView.priceView?.isHidden = nativeAd.price == nil

        (nativeAdView.advertiserView as? UILabel)?.text = nativeAd.advertiser
        nativeAdView.advertiserView?.isHidden = nativeAd.advertiser == nil

        nativeAdView.callToActionView?.isUserInteractionEnabled = false

        nativeAdView.nativeAd = nativeAd
    }
    func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) {
        print("\(adLoader) failed with error: \(error.localizedDescription)")
    }
}
```
```ContentView.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        NativeView()
            .frame(height: 160)
    }
}
```
完成！！！
![IMG_0257.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b5119bbb-f96a-3bb2-6f15-0923a5e52d7b.png)
いい感じになりました

# おわり
今回作成したプロジェクトを置いとくので参考にしてください。

https://github.com/SNQ-2001/AdMob-Native-Demo