1. IOS – Monetize App ...
  2. User Manual
  3. Formaty Reklam
  4. Infinite Scroll

Infinite Scroll

Prerequisites

The SDK provides a universal way to display advertisements inside the cell of scrollable controls, such as UITableView and UICollectionView.

Keep in mind that the cell item should provide an empty wrapper view to the SDK, so the SDK will use that wrapper view to place an advertisement in it. Therefore the cell size should be dynamic, because the advertisement size is dynamic as well.

As an alternative approach, to manually adjust cell’s layout, track the size of the advertisement by using childAdLifecycle parameter of RefineryAdFactory.shared.getInfiniteScrollAdForIndex method.


Display Ad Inside UITableView

To place an Ad inside the cell item, SDK provides three main methods, one to generate infiniteScrollID via calling RefineryAdFactory.shared.createManualInfiniteScroll, next to place an ad inside the wrapper for the cell position RefineryAdFactory.shared.getInfiniteScrollAdForIndex(...), and the last to hide the advertisement for a position RefineryAdFactory.shared.hideInfiniteScrollAdForIndex(...).

1. Prepare the Item Cell

Let’s start by creating a cell item, the AdItemCell. It contains two child views, one is the UILabel which will display the cell position, and the other is UIView which is the wrapper container for the advertisement.

        class AdItemCell: UITableViewCell {
            let centeredLabel = UILabel()
            let adContainer:UIView = {
                let view = UIView()
                view.translatesAutoresizingMaskIntoConstraints = false
                return view
            }()
            
            private var position:Int32 = -1;
            private var infiniteScrollId:Int32 = -1;
            …
            override func prepareForReuse() {
                if position != -1 && infiniteScrollId != -1 {
                    // Hide the advertisement for a given position
                    RefineryAdFactory.shared.hideInfiniteScrollAdForIndex(infiniteScrollId: infiniteScrollId, itemIndex: position)
                }
            }
            
            // This method is get called from the UITableViewDataSource.
            func loadAd(position:Int32,infiniteScrollId:Int32){
                self.position = position
                self.infiniteScrollId = infiniteScrollId
                // Show the advertisement for a given position
                RefineryAdFactory.shared.getInfiniteScrollAdForIndex(infiniteScrollId: infiniteScrollId, itemIndex: position, itemAdWrapper: adContainer, childAdLifecycle: BannerEventListener())
            }
            …
        }
    

Strona loadAd() method is called from the UITableViewDataSource whenever the cellForRowAt delegate method is called, and it uses the getInfiniteScrollAdForIndex method to let the SDK determine whether to place an Ad for a given position or not.

Strona prepareForReuse() method is called whenever the cell will be reused, so for that, we need to request SDK to hide the advertisement hideInfiniteScrollAdForIndex, because after reusing the cell, a new position will be assigned to the cell and the cell might not be needed to display the ad for its new position.

2. Prepare the UITableView

Next is to generate infiniteScrollId by using RefineryAdFactory.shared.createManualInfiniteScroll method

        class InfiniteScrollViewController: UIViewController {

            var tableView:UITableView!
            var infiniteScrollId: Int32!
            
            override func viewDidLoad() {
                super.viewDidLoad()
                // Generate the infiniteScrollId
                let infiniteScrollConfigID = ConfigBuilder.companion.INFINITE_SCROLL_TEST_R89_CONFIG_ID
                infiniteScrollId = RefineryAdFactory.shared.createManualInfiniteScroll(configurationID: infiniteScrollConfigID, lifecycleCallbacks: nil)
                
                // Table view configuration
                tableView = UITableView(frame: self.view.bounds, style: .plain)
                tableView.register(AdItemCell.self, forCellReuseIdentifier: “cell”)
                tableView.dataSource = self
                tableView.delegate = self
                tableView.rowHeight = UITableView.automaticDimension
                
                self.view.addSubview(tableView)
                
                …
            }
        }
    

3. Prepare the UITableViewDelegate i UITableViewDataSource

Last, we need to bind together the cell and the table view.

        extension InfiniteScrollViewController: UITableViewDelegate, UITableViewDataSource {

            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                return 1000
            }
            
            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                let cell = tableView.dequeueReusableCell(withIdentifier: “cell”, for: indexPath) as! AdItemCell
                cell.centeredLabel.text = “Row \(indexPath.row)”
                // Here we set the item’s position and generated infiniteScrollId
                cell.loadAd(position: Int32(indexPath.row), infiniteScrollId: Int32(infiniteScrollId))
                return cell
            }
        }
    

Inside the cellForRowAt delegate’s method, we are passing the generated infiniteScrollId to the cell item.

Lifecycle Events

There are two paths available to track the advertisement events for the infinite scroll.

The first one is the general event listener, which notifies about all Ad events in the scrollable view.
Use InfiniteScrollEventListener to listen to general events in the scroll view by passing its instance to RefineryAdFactory.shared.createManualInfiniteScroll method while generating an infiniteScrollId, as demonstrated below

        override func viewDidLoad() {
            super.viewDidLoad()
            …
            let infiniteScrollConfigID = ConfigBuilder.companion.INFINITE_SCROLL_TEST_R89_CONFIG_ID
            infiniteScrollId = RefineryAdFactory.shared.createManualInfiniteScroll(configurationID: infiniteScrollConfigID, lifecycleCallbacks: LoggerInfiniteScrollEventListener())
            …
        }
    

Here is the implementation of LoggerInfiniteScrollEventListener.

        class LoggerInfiniteScrollEventListener: InfiniteScrollEventListener{
            override func onRoll(itemIdInData: Int32) {
                print(“onRoll”,”itemIdInData=\(itemIdInData)”)
            }
            
            override func onRollFailed(itemIdInData: Int32) {
                print(“onRollFailed”,”itemIdInData=\(itemIdInData)”)
            }
            
            override func onAdItemFailedToCreate(message: String) {
                print(“onAdItemFailedToCreate”,”message=\(message)”)
            }
            
            override func onAdItemOpen(itemIdInData: Int32) {
                print(“onAdItemOpen”,”itemIdInData=\(itemIdInData)”)
            
            }
            
            override func onAdItemClick(itemIdInData: Int32) {
                print(“onAdItemClick”,”itemIdInData=\(itemIdInData)”)
            
            }
            
            override func onAdItemClose(itemIdInData: Int32) {
                print(“onAdItemClose”,”itemIdInData=\(itemIdInData)”)
            
            }
            
            override func onAdItemLoaded(itemIdInData: Int32) {
                print(“onAdItemLoaded”,”itemIdInData=\(itemIdInData)”)
            
            }
            
            override func onAdItemImpression(itemIdInData: Int32) {
                print(“onAdItemImpression”,”itemIdInData=\(itemIdInData)”)
            
            }
            
            override func onAdItemCreated(adapterId: Int32, probability: Double) {
                print(“onAdItemCreated”,”adapterId=\(adapterId)”,”probability=\(probability)”)
            
            }
            
            override func onAdItemFailedToLoad(itemIdInData: Int32, error: R89LoadError) {
                print(“onAdItemFailedToLoad”,”itemIdInData=\(itemIdInData)”,”error=\(error)”)
            }
        }
    

The other way to track advertisement lifecycle events is to pass an instance of BannerEventListenerto the RefineryAdFactory.shared.getInfiniteScrollAdForIndex method. In contrast with the first approach, this one will listen to a single advertisement’s lifecycle events for a given position.

        func loadAd(position:Int32,infiniteScrollId:Int32){
            self.position = position
            self.infiniteScrollId = infiniteScrollId
            // Show the advertisement for a given position
            RefineryAdFactory.shared.getInfiniteScrollAdForIndex(infiniteScrollId: infiniteScrollId, itemIndex: position, itemAdWrapper: adContainer, childAdLifecycle: BanneEventLogger())
        }
    

Here is the implementation of BanneEventLogger.

        class BanneEventLogger: BannerEventListener {
            override func onLayoutChange(width: Int32, height: Int32) {
                print(“onLayoutChange”,”width=\(width)”,”height=\(height)”)
            }
            
            override func onLoaded() {
                print(“onLoaded”)
            }
            
            override func onOpen() {
                print(“onOpen”)
            }
            
            override func onClick() {
                print(“onClick”)
            }
            
            override func onClose() {
                print(“onClose”)
            }
            
            override func onImpression() {
                print(“onImpression”)
            }
            
            override func onFailedToLoad(error: R89LoadError) {
                print(“onFailedToLoad”,”error=\(error)”)
            }
        }
    

Jak możemy pomóc?