Facebook Audience Network(Native AD) を利用してTableViewに広告を出す

Facebook Audience Networkを利用して、タイムラインに広告を表示する実装のメモ。

## Facebook Audience Network(Native AD)

### 利用したライブラリバージョン
5.6.0

### ざっくり概要

- 自分のアプリのUXにあった広告を表示する事が出来る
- 画像やタイトルといった広告表示に必要な情報を受けてれる
- [ガイドライン](https://developers.facebook.com/docs/audience-network/guidelines/native-ads#native)には沿うこと

## 基本的な使い方
### FBAudienceNetworkのインストール

```
// Podfileに以下を追記
pod 'FBAudienceNetwork'
```

### 広告用Viewの用意

[公式ドキュメント](https://developers.facebook.com/docs/audience-network/guides/ad-formats/native/ios#ui) 通りに必要な要素をStoryboardでぽちぽち貼ればOK

0. advertiser icon
0. ad title
0. sponsored label
0. advertiser choice
0. ad media view
0. social context
0. ad body
0. ad call to action button

![42521210_351346438936188_3537153512423030784_n.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172074/262510e6-af94-3757-d8de-e348b59406bb.png)

参考：表示項目の必須判断は[こちら](https://developers.facebook.com/docs/audience-network/guidelines/native-ads#native)の方が解りやすかったです。

### FBNativeAdDelegateの組み込み

あとは、広告を表示したいViewControllerでFBNativeAdDelegateのprotocolを実装すれば良い。[FBNativeAd](https://developers.facebook.com/docs/reference/ios/current/class/FBNativeAd/) を利用してViewに広告情報を反映する。

```
extension ViewController: FBNativeAdDelegate {
    
    // 基本的にはこの中で取得したデータをViewにセットする
    func nativeAd(_ nativeAd: FBNativeAd, didFailWithError error: Error) {
　　　　 if nativeAd.isAdValid {
           // TODO Viewへのデータセット
           // 必要なかったので、Viewへの貼り付けはしていないですが
           // 後半のTableViewの内容が参考になると思います。
        }
    }
    
    // ADのクリック終了後に呼ばれる
    func nativeAdDidFinishHandlingClick(_ nativeAd: FBNativeAd) {
        // 必要に応じて実装
    }
    
    // ADがキャプチャされた時に呼ばれる
    func nativeAdWillLogImpression(_ nativeAd: FBNativeAd) {
        // 必要に応じて実装
    }
    
    // ADのメディアダウンロード時に呼ばれる
    func nativeAdDidDownloadMedia(_ nativeAd: FBNativeAd) {
        // 必要に応じて実装
    }
    
    // ADのロード時に呼ばれる
    func nativeAdDidLoad(_ nativeAd: FBNativeAd) {
        // 必要に応じて実装
    }
    
    // ADのクリック時に呼ばれる
    func nativeAdDidClick(_ nativeAd: FBNativeAd) {
        // 必要に応じて実装
    }
}
```

## TableViewでの使い方

### 利用するクラス
[FBNativeAdsManager](https://developers.facebook.com/docs/reference/ios/current/class/FBNativeAdsManager/)：アプリ内に表示するADの管理
[FBNativeAdTableViewCellProvider](https://developers.facebook.com/docs/reference/ios/current/class/FBNativeAdTableViewCellProvider/)：TableViewCellでADを表示する際のサポートクラス

### 実装

ViewControllerにProtocolを設定

```
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, FBNativeAdDelegate, FBNativeAdsManagerDelegate {
```

Protocolの実装とFBNativeAdsManagerのセットアップ

```
override func viewDidLoad() {
        super.viewDidLoad()

        // FBNativeAdsManagerの設定と広告読み込み
        fbAdsManager = FBNativeAdsManager(placementID: "プレイスメントID", forNumAdsRequested: 3)
        fbAdsManager.delegate = self
        fbAdsManager.loadAds()
}

// 広告が読み込まれると呼ばれる
func nativeAdsLoaded() {
　　　　　// FBNativeAdTableViewCellProviderの設定
        fbAdsTableViewCellProvider = FBNativeAdTableViewCellProvider(manager: fbAdsManager, for: .genericHeight300)
        fbAdsTableViewCellProvider.delegate = self

        // TableViewのリロード
        if self.tableView != nil {
            self.tableView.reloadData()
        }
}

func nativeAdsFailedToLoadWithError(_ error: Error) {
        // Error handling
}

```

FBNativeAdTableViewCellProividerを利用したTableViewの調整

```
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if fbAdsTableViewCellProvider != nil {
            return Int(fbAdsTableViewCellProvider.adjustCount(<本来のデータ数>, forStride: UInt(fbAdRowStep)))
        }
        return <本来のデータ数>
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if fbAdsTableViewCellProvider != nil && fbAdsTableViewCellProvider.isAdCell(at: indexPath as IndexPath, forStride: UInt(fbAdRowStep)) {

            let cell = self.tableView.dequeueReusableCell(withIdentifier: "FbAdCell", for: indexPath) as! FbAdCell
et fbNativeAd = fbAdsManager.nextNativeAd
            fbNativeAd?.unregisterView()
            fbNativeAd?.registerView(forInteraction: cell.adUIView, mediaView: cell.adCoverMediaiew, iconView: cell.adIconImageView, viewController: self, clickableViews: [cell.adCallToActionButton])
            cell.fbNativeAd = fbNativeAd
            return cell
        }
        // オリジナルのcellに対する情報追加処理
        return tableView.dequeueReusableCell(withIdentifier: "OriginalCell", for: indexPath as IndexPath)
}
```

Facebook広告用のTableCellの作成

```
import UIKit
import FBAudienceNetwork

final class FacebookADCell: UITableViewCell {

    @IBOutlet weak var adUIView: UIView!
    @IBOutlet weak var adContentView: UIView!
    @IBOutlet weak var adIconImageView: FBAdIconView!
    @IBOutlet weak var adCoverMediaiew: FBMediaView!
    @IBOutlet weak var adTitleLabel: UILabel!
    @IBOutlet weak var adBodyLabel: UILabel!
    @IBOutlet weak var adCallToActionButton: RadiusButton!
    @IBOutlet weak var sponseredLabel: UILabel!
    @IBOutlet weak var adChoicesView: FBAdChoicesView!

    var fbNativeAd: FBNativeAd! {
        didSet {
            adTitleLabel.text = fbNativeAd.advertiserName
            adBodyLabel.text = fbNativeAd.bodyText
            sponseredLabel.text = fbNativeAd.sponsoredTranslation
            adCallToActionButton.setTitle(fbNativeAd.callToAction, for: .normal)
            adChoicesView.nativeAd = fbNativeAd
        }
    }
    override func draw(_ rect: CGRect) {
        super.draw(rect)
    }

    override func awakeFromNib() {
        super.awakeFromNib()

    }
}
```