Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display xib in current collection view

This is my first time working with Google AdMob native ads, I believe I followed the implementation instruction.. All that is left is actually displaying the ads within the collection view, and this is where I am stuck. I do not know how to correctly display the Ads in between users uploaded post. Basically I need help adding a xib to a collection view. task: Ads should be populating while scrolling through posts..

I am using

Collection View Xib Google AdMob Native advanced

I also do not receive any errors or crashes, and the console prints so I am obviously doing something wrong.. Received native ad:

The console also - print("Ads not dispalying ") and print("Not what I want")

Heres my code

import UIKit
import Firebase


class FollowingFeedViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UISearchBarDelegate, FeedCellDelegate, PeopleToFollowDelegate,  GADUnifiedNativeAdLoaderDelegate {



    // MARK: - Google ADMob

       /// The ad unit ID from the AdMob UI.
        let adUnitID = "ca-app-pub-3940256099942544/3986624511"


        /// The number of native ads to load (between 1 and 5 for this example).
        let numAdsToLoad = 5

        /// The native ads.
        var nativeAds = [GADUnifiedNativeAd]()

        /// The ad loader that loads the native ads.
        var adLoader: GADAdLoader!

        func adLoaderDidFinishLoading(_ adLoader: GADAdLoader) {

             addNativeAds() 
     }

       func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADUnifiedNativeAd) {
        print("Received native ad: \(nativeAd)")

        // Add the native ad to the list of native ads.
        nativeAds.append(nativeAd)
    }

     func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) {
        print("\(adLoader) failed with error: \(error.localizedDescription)")

    }


    /// Add native ads to the  list.
     func addNativeAds() {
       if nativeAds.count <= 0 {
       print("Ads not dispalying ")
        return
       }

       let adInterval = (posts.count / nativeAds.count) + 1
       var index = 0
       for nativeAd in nativeAds {
         if index < collectionObject.count {
           collectionObject.insert(nativeAd, at: index)
           index += adInterval
         } else {
            print("Not what I want")

           break
         }
       }
     }

 // MARK: - Properties

    var posts = [Post]()
    var collectionObject = [AnyObject]()
    var viewSinglePost = false
    var post: Post?
    var currentKey: String?
    var userProfileController: ProfileViewController?
    var header: FeedReusableView?
    @IBOutlet weak var collectionView: UICollectionView!

 // MARK: - UICollectionViewDataSource

     func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        if posts.count > 4 {
            if indexPath.item == posts.count - 1 {
                fetchPosts()

            }
        }
    }




    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

            return posts.count


    }

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PostsCell", for: indexPath) as? FollowingCell {

            cell.delegate = self
            cell.post = posts[indexPath.item] as Post


            handleUsernameLabelTapped(forCell: cell)
            handleMentionTapped(forCell: cell)
            handleHashtagTapped(forCell: cell)

            return cell

     } else {

    let nativeAd = collectionObject[indexPath.row] as! GADUnifiedNativeAd

            nativeAd.rootViewController = self

            let nativeAdCell = collectionView.dequeueReusableCell(withReuseIdentifier: "UnifiedNativeAdCell", for: indexPath)

            // Get the ad view from the Cell. The view hierarchy for this cell is defined in

                 let adView : GADUnifiedNativeAdView = nativeAdCell.contentView.subviews
                   .first as! GADUnifiedNativeAdView

            // Associate the ad view with the ad object.
            // This is required to make the ad clickable.

            adView.nativeAd = nativeAd

            adView.mediaView?.mediaContent = nativeAd.mediaContent

            // Populate the ad view with the ad assets.
            (adView.headlineView as! UILabel).text = nativeAd.headline
            (adView.advertiserView as! UILabel).text = nativeAd.advertiser
            (adView.bodyView as! UILabel).text = nativeAd.body
            adView.bodyView?.isHidden = nativeAd.body == nil
            (adView.iconView as? UIImageView)?.image = nativeAd.icon?.image
            adView.iconView?.isHidden = nativeAd.icon == nil

            // In order for the SDK to process touch events properly, user interaction
            // should be disabled.
            adView.callToActionView?.isUserInteractionEnabled = false


        return nativeAdCell


        }


    }

 // MARK: - ViewDidLoad

    override func viewDidLoad() {
        super.viewDidLoad()

//        // Google Admob
        let options = GADMultipleAdsAdLoaderOptions()
        options.numberOfAds = numAdsToLoad

  // Prepare the ad loader and start loading ads.
     adLoader = GADAdLoader(adUnitID: adUnitID,
      rootViewController: self,
      adTypes: [.unifiedNative],
      options: [options])


 collectionView.dataSource = self
 collectionView.delegate = self

 adLoader.delegate = self
 adLoader.load(GADRequest())

self.collectionView.register(UINib(nibName: "NativeAdCell", bundle: nil), forCellWithReuseIdentifier: "UnifiedNativeAdCell")

        addNativeAds()

}

  @objc func handleRefresh() {
        posts.removeAll(keepingCapacity: false)
        self.currentKey = nil
        fetchPosts()
        collectionView?.reloadData()
        header?.profilesCollectionView.reloadData()


    }



}

Fetch Post


func fetchPosts() {
        guard let currentUid = Auth.auth().currentUser?.uid else { return }

        if currentKey == nil {
            USER_FEED_REF.child(currentUid).queryLimited(toLast: 5).observeSingleEvent(of: .value, with: { (snapshot) in
                self.collectionView?.refreshControl?.endRefreshing()

                guard let first = snapshot.children.allObjects.first as? DataSnapshot else { return }
                guard let allObjects = snapshot.children.allObjects as? [DataSnapshot] else { return }

                allObjects.forEach({ (snapshot) in
                    let postId = snapshot.key
                    self.fetchPost(withPostId: postId)
                })
                self.currentKey = first.key
            })
        } else {

            USER_FEED_REF.child(currentUid).queryOrderedByKey().queryEnding(atValue: self.currentKey).queryLimited(toLast: 6).observeSingleEvent(of: .value, with: { (snapshot) in

                guard let first = snapshot.children.allObjects.first as? DataSnapshot else { return }
                guard let allObjects = snapshot.children.allObjects as? [DataSnapshot] else { return }

                allObjects.forEach({ (snapshot) in
                    let postId = snapshot.key
                    if postId != self.currentKey {
                        self.fetchPost(withPostId: postId)
                    }
                })
                self.currentKey = first.key
            })
        }
    }

 func fetchPost(withPostId postId: String) {
        Database.fetchPost(with: postId) { (post) in
            self.posts.append(post)

            self.posts.sort(by: { (post1, post2) -> Bool in
            return post1.creationDate > post2.creationDate
            })
            self.collectionView?.reloadData()
        }
    }

}



like image 587
Clint Avatar asked Nov 24 '25 04:11

Clint


2 Answers

I think this will work, you have two data source as I can see from your code

var posts = [Post]()
var collectionObject = [AnyObject]()

and you want to create cell for all of them but the only data source you are going to show is posts based on your code

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return posts.count
}

this can be solved by changing your code to something like this

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 2
}

 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if (section == 0) {
            return posts.count
        } else {
            return collectionObject.count
        }
}

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    if (indexPath.section == 0) {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PostsCell", for: indexPath) as FollowingCell 

            cell.delegate = self
            cell.post = posts[indexPath.item] as Post


            handleUsernameLabelTapped(forCell: cell)
            handleMentionTapped(forCell: cell)
            handleHashtagTapped(forCell: cell)

            return cell

    } else {
        let nativeAd = collectionObject[indexPath.row] as! GADUnifiedNativeAd

        nativeAd.rootViewController = self

        let nativeAdCell = collectionView.dequeueReusableCell(withReuseIdentifier: "UnifiedNativeAdCell", for: indexPath)

        // Get the ad view from the Cell. The view hierarchy for this cell is defined in

             let adView : GADUnifiedNativeAdView = nativeAdCell.contentView.subviews
               .first as! GADUnifiedNativeAdView

        // Associate the ad view with the ad object.
        // This is required to make the ad clickable.

        adView.nativeAd = nativeAd

        adView.mediaView?.mediaContent = nativeAd.mediaContent

        // Populate the ad view with the ad assets.
        (adView.headlineView as! UILabel).text = nativeAd.headline
        (adView.advertiserView as! UILabel).text = nativeAd.advertiser
        (adView.bodyView as! UILabel).text = nativeAd.body
        adView.bodyView?.isHidden = nativeAd.body == nil
        (adView.iconView as? UIImageView)?.image = nativeAd.icon?.image
        adView.iconView?.isHidden = nativeAd.icon == nil

        // In order for the SDK to process touch events properly, user interaction
        // should be disabled.
        adView.callToActionView?.isUserInteractionEnabled = false


    return nativeAdCell


    }

}

This code first add posts and then start adding your adds. Check this and let me know if it's worked or not. If this show the cell then you can mix two data source together and populate your collection view cells with condition like if you create new object that math this condition with your current object posts & collectionObject

if indexPath.item % 4 == 0 {
   show adds
} else {
   show posts
}

Hope this will help

like image 63
Arashk Avatar answered Nov 25 '25 18:11

Arashk


Your FollowingFeedViewController is not a subclass from UICollectionViewController, right? Because of that, you should set the delegate and dataSource properties of your collectionView instance.

Probably something like this:

override func viewDidLoad() {
  super.viewDidLoad()
  collectionView.delegate = self
  collectionView.dataSource = self
}
like image 34
Matheus Sousa Avatar answered Nov 25 '25 20:11

Matheus Sousa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!