DFPのiOS SDKを使って、UITableViewCellにネイティブ広告（GADNativeContentAd）を配信するサンプル

DFP(DoubleClick for Publishers)でiOSアプリに広告を出すサンプルが日本語、英語どちらにも見当たらず、試行錯誤したのでこれからDFPをiOSアプリで使う人の参考になれば幸いです。
UITableViewのセルにGADNativeContentAdを表示するサンプルです。
DFPを使うことでiosでネイティブ広告や、自社広告の管理が出来るようになります。

なお、DFPの設定方法についてはここでは割愛します。

サンプルソース
https://github.com/nishiyamaosamu/DFPNaiveContentAdInTableViewCellSample

画面はこんな感じ
![image](https://qiita-image-store.s3.amazonaws.com/0/24308/2fd18e6d-22f2-1573-fc64-5ecc6270ebdf.png)

↑これはAdsense広告がサンプルとして配信されていますが、DFPを使って、自社広告を入れることも可能です。その場合右上の[Ads by Google]は表示されません。

#要点解説

自分が工夫したり、ハマったりしたところの要点を解説します。

まずはViewControllerのソースです。

```swift:ViewController.swift
import UIKit
import GoogleMobileAds

class ViewController: UITableViewController,UITableViewDelegate,UITableViewDataSource,GADAdLoaderDelegate,
    GADNativeContentAdLoaderDelegate
{
    
    let firstAdsPositionInCells = 3
    let frequencyAdsInCells = 10
    var adLoader : GADAdLoader!
    var nativeContentAdView : GADNativeContentAdView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        tableView.delegate = self
        tableView.dataSource = self
        
        //DFP
        self.adLoader = GADAdLoader(adUnitID: "/6499/example/native", rootViewController: self, adTypes: [kGADAdLoaderAdTypeNativeContent], options: [])
        self.adLoader.delegate = self
        let request = DFPRequest()
        request.testDevices = [ kGADSimulatorID ]
        self.adLoader.loadRequest(request)
        
        
        nativeContentAdView = UINib(nibName: "NativeContentAdView", bundle: nil).instantiateWithOwner(self, options: nil)[0] as! GADNativeContentAdView
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func adLoader(adLoader: GADAdLoader!, didFailToReceiveAdWithError error: GADRequestError!) {
    }
    
    func adLoader(adLoader: GADAdLoader!, didReceiveNativeContentAd nativeContentAd: GADNativeContentAd!) {
        nativeContentAdView.nativeContentAd = nativeContentAd
        (nativeContentAdView.headlineView as! UILabel).text = nativeContentAd.headline
        (nativeContentAdView.bodyView as! UILabel).text = nativeContentAd.body
        if let nativeAdImage = nativeContentAd!.images.first as? GADNativeAdImage {
            (nativeContentAdView.imageView as! UIImageView).image = nativeAdImage.image
        }
        
        self.tableView.reloadData()
    }
    
    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 100.0
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }
    
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->  UITableViewCell {
        var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
        
        let isAdsPosition = (indexPath.row % frequencyAdsInCells - firstAdsPositionInCells) == 0
        
        if isAdsPosition && self.nativeContentAdView.nativeContentAd != nil {
            nativeContentAdView.frame = cell.contentView.frame
            cell.contentView.addSubview(nativeContentAdView)
        }else{
            if self.nativeContentAdView.isDescendantOfView(cell.contentView) {
                nativeContentAdView.removeFromSuperview()
            }
            cell.textLabel?.text = indexPath.row.description
        }
        return cell
    }
    
    
}
```

・まずはViewControllerのViewDidLoadで広告のリクエストを行います。本番では`request.testDevices`は除いてください。

・リクエスト後の結果についてデリゲートしたメソッドで受け取ります。リクエスト後に、`tableView.reloadData()`でテーブルを更新します。

```swift
    func adLoader(adLoader: GADAdLoader!, didReceiveNativeContentAd nativeContentAd: GADNativeContentAd!) {
        nativeContentAdView.nativeContentAd = nativeContentAd
        (nativeContentAdView.headlineView as! UILabel).text = nativeContentAd.headline
        (nativeContentAdView.bodyView as! UILabel).text = nativeContentAd.body
        if let nativeAdImage = nativeContentAd!.images.first as? GADNativeAdImage {
            (nativeContentAdView.imageView as! UIImageView).image = nativeAdImage.image
        }
        
        self.tableView.reloadData()
    }
```

・DPFはクリックイベントを取得するために、`GADNativeContentAdView`というのをaddViewする必要があります。CustomCellをつくるのではなく、GADNativeContentAdViewのViewファイルを作り、それを`cell.contentView`にaddViewする必要があります。

```swift
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->  UITableViewCell {

...

nativeContentAdView.frame = cell.contentView.frame
cell.contentView.addSubview(nativeContentAdView)

...
}

```
・UITableViewCellは再利用されるので、addViewすると延々と追加されてしまいます。そのため単一の`GADNativeContentAdView`を使うべく、ViewControllerに`GADNativeContentAdView`のメンバ変数を作って、それを使い回します。

```swift
var nativeContentAdView : GADNativeContentAdView!
```

※こちらのAdmobの例を参考にしました
http://googleadsdeveloper.blogspot.jp/2012/03/embedding-google-admob-ads-within.html


・`GADNativeContentAdView`が再度表示されてくるタイミングで再利用されますが、再利用される前に、`GADNativeContentAdView`が入ったセルが再利用されると残ってしまうので、広告表示ではないセルに、`GADNativeContentAdView`が含まれている場合にはremoveFromSuperViewで削除するように工夫しています。

```swift    
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->  UITableViewCell {

...

if self.nativeContentAdView.isDescendantOfView(cell.contentView) {
        nativeContentAdView.removeFromSuperview()
}

...

}
```

・`GADNativeContentAdView`をViewファイルで作ります。クラスに`GADNativeContentAdView`を指定します。

・それぞれのUILabelやUIImageViewは`GADNativeContentAdView`のOutletと結びつけます。

![image](https://qiita-image-store.s3.amazonaws.com/0/24308/4b9eeea0-244a-be14-c747-9bab096a6372.png)


以上、おおまかに要点のみ記述しました。
あとは、公式のマニュアルと照らしあわせて貰えればと思います。

#ハマったところ
・`GADNativeContentAdView`をcell.contentViewにaddSubviewせずに、カスタムセルを作ってやろうとしたら、クリック出来ないことを知った。
・`GADNativeContentAdView`をcellの更新の都度生成し、addSubviewしてたら、延々とViewが増えてしまった。
・上記に書いた「Embedding Google AdMob Ads Within A UITableView」の記事で、GADBannerViewが再利用されるということでやったが、再利用のタイミングによっては、removeFromSubviewをしないとViewが存在したままでダメだった。



#公式：SDK for DFP Users on iOS
https://developers.google.com/mobile-ads-sdk/docs/dfp/ios/native