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()
}
}
}
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
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With