> For the complete documentation index, see [llms.txt](https://aatkit.gitbook.io/ios-integration/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://aatkit.gitbook.io/ios-integration/formats/banner/banner-cache.md).

# Banner Cache

Integrate Banner Cache

The [banner cache](https://docs.gravite.net/aatkit/ios/docs/documentation/aatkit/aatbannercache) is a special tool to help you integrate infeed banners more easily. It will wrap an infeed banner and use it to automatically preload banner ads, aiming to have a defined amount of banners available for an immediate handout to the app whenever they are needed. Compared to using the [infeed banner](/ios-integration/formats/banner/infeed-banner.md) directly, it comes with the following

**Pros**

* Automatically caches banner ads, so your app can consume and present them whenever needed (i.e. when the dedicated feed cell enters the visible area of the screen)
* Automatically takes care of correct ad space counting (it counts an ad space whenever you try to consume an ad because we assume, you only consume an ad when you need to present it right now).
* Allows server-side configuration of frequency capping: You can configure frequency capping for banner cache placements within the Dashboard at page "Settings / Placements" (e.g. show not more than 1 impression per hour), so you don’t need to implement frequency capping yourself.

**Cons**

* You cannot specify specific configurations for the ad request (like e.g. keyword targeting X for the first ad request and keyword targeting Y for the next one and so on) and control the load cycle of a specific ad.

{% hint style="info" %}
We strongly recommend using the banner cache instead of the infeed banner, unless you actually need to control the ad request configuration separately per loaded ad (e.g. in very specific targeting scenarios per ad position in the feed).
{% endhint %}

### Create Banner Cache

{% tabs %}
{% tab title="Swift" %}

```swift
let configuration = AATBannerCacheConfiguration(placementName: "<PLACEMENT_NAME>", size: 3)
configuration.delegate = self
bannerCache = AATSDK.createBannerCache(configuration: configuration)
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
AATBannerCacheConfiguration *configuration = [[AATBannerCacheConfiguration alloc] initWithPlacementName:@"<PLACEMENT_NAME>" size:3];
configuration.delegate = self;
self.bannerCache = [AATSDK createBannerCacheWithConfiguration:configuration];
```

{% endtab %}
{% endtabs %}

#### **Banner Cache Configuration**

[AATBannerCacheConfiguration](https://docs.gravite.net/aatkit/ios/docs/documentation/aatkit/aatbannercacheconfiguration) can be configured with the following:

* `placementName` defines the name of the internally wrapped placement (e.g. important for the statistics on the Dashboard).
* `size` defines how many preloaded banners should be available in the cache. Max value: 5.

{% hint style="info" %}
Starting with AATKit 3.15, you can skip the size parameter to let banner the cache try to automatically adjust its size.
{% endhint %}

{% hint style="info" %}
We recommend starting with a cache size of 1 and testing, if all your ad spaces get filled. If not, increase the cache size by 1 and repeat your test. The general rule should be: use the smallest possible cache size to achieve good fill rates but avoid waisting ads at the same time. Waisted ads may influence paid prices in a negative way.
{% endhint %}

* `delegate` an instance of [AATBannerCacheDelegate](https://docs.gravite.net/aatkit/ios/docs/documentation/aatkit/aatbannercachedelegate) that will notify you when the first banner is loaded and ready to be consumed.
* `requestConfiguration` an instance of [AATBannerRequest](https://docs.gravite.net/aatkit/ios/docs/documentation/aatkit/aatbannerrequest) that will be used internally for requesting banner ads from the `AATInfeedBannerPlacement`.
* `minDelay` represents the minimum delay between two banner consumptions in seconds. Useful to prevent consuming too many ads when the user is fast scrolling. Default: 1 s.
* `shouldCacheAdditionalAdAtStart` defines if the cache should load an additional ad at the beginning. `false` by default.

**Configure Banner Request**

See the [banner request configuration](/ios-integration/formats/banner/infeed-banner.md#configure-aatbannerrequest) for infeed banner placement.

{% tabs %}
{% tab title="Swift" %}

```swift
let request = AATBannerRequest(delegate: self)
request.targetingInformation = ["key": ["value"]]
request.contentTargetingUrl = "http://example.com/similar/content"
OR
request.multiContentTargetingUrls = ["URL1", "URL2"]
request.setRequestBannerSizes(sizes: Set(arrayLiteral: .banner320x53, .banner300x250))
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
AATBannerRequest *request = [[AATBannerRequest alloc] initWithDelegate:self];
NSSet *sizes = [[NSSet alloc] initWithArray:@[@(AATBannerSizeBanner320x53), @(AATBannerSizeBanner300x250), @(AATBannerSizeBanner320x100)]];
[request setRequestBannerSizes:sizes];
request.targetingInformation = @{@"Key": @[@"value"]};
request.contentTargetingUrl = @"http://example.com/similar/content";
OR
request.multiContentTargetingUrls = @[@"URL1", @"URL2"];
```

{% endtab %}
{% endtabs %}

### Consume Banners

To consume banners, use this API: `func consume(force: Bool = false) -> AATBannerPlacementWrapperView?`. It returns an instance of UIView to be used within the app. Can return nil if there are no banners available in the cache. Also automatically counts an ad space. BannerCache will no longer hold any references to returned banners, and they need to be destroyed manually by the app.

If the `force` parameter is true, the `minDelay` parameter of the [AATBannerCacheConfiguration](https://docs.gravite.net/aatkit/ios/docs/documentation/aatkit/aatbannercacheconfiguration) instance will be ignored.

{% tabs %}
{% tab title="Swift" %}

```swift
let bannerView = bannerCache.consume()
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
UIView *bannerView = [bannerCache consumeWithForce:NO];
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The ads are served from the cache using a 'first in, first out' (FIFO) approach, meaning the oldest loaded banners are displayed first.
{% endhint %}

### Cache Status Delegate

To listen to the banner cache status, conform to the [`AATBannerCacheStatusDelegate`](https://docs.gravite.net/aatkit/ios/docs/documentation/aatkit/aatbannercachestatusdelegate) and set the banner cache `cacheStatusDelegate` property.

{% tabs %}
{% tab title="Swift" %}

```swift
bannerCache?.cacheStatusDelegate = self
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
self.bannerCache.cacheStatusDelegate = self;
```

{% endtab %}
{% endtabs %}

### Complete Code Example

{% tabs %}
{% tab title="Swift" %}

```swift
class ViewController: UIViewController {

    private var bannerCache: AATBannerCache?

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // [IMPORTANT] Notify AATKit about the currently active view controller
        AATSDK.controllerViewDidAppear(controller: self)

        // Create banner cache configuration instance
        let configuration = AATBannerCacheConfiguration(placementName: "<PLACEMENT_NAME>", size: 1)
        configuration.delegate = self
        
        // Create the banner request instance
        let request = AATBannerRequest(delegate: self)
        // Configure request banner sizes
        request.setRequestBannerSizes(sizes: Set([.banner320x53, .banner300x250]))
        // Configure request targeting information
        request.contentTargetingUrl = "http://example.com/similar/content"
        // OR
        request.multiContentTargetingUrls = ["URL1", "URL2"]
        // Configure request content targeting URL
        request.targetingInformation = ["key": ["value"]]
        // Set configuration banner request
        configuration.requestConfiguration = request

        // Create the banner cache (once it has been created, it would start loading automatically)
        bannerCache = AATSDK.createBannerCache(configuration: configuration)
        
        // Setting banner cache status delegate
        bannerCache?.cacheStatusDelegate = self
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // Destroy the banner cache when it's not needed anymore
        bannerCache?.destroy()
        
        // [IMPORTANT] Remove the currently active view controller
        AATSDK.controllerViewWillDisappear()
    }
}

extension ViewController: AATBannerCacheDelegate {
    func firstBannerLoaded() {
        // Get the banner view
        guard let bannerView = bannerCache?.consume() else {
            print("An error occurred")
            return
        }
        // Change bannerView frame (or constraints) to the desired location on the screen
    }
}

extension ViewController: AATBannerCacheStatusDelegate {
    func cacheIsNoLongerEmpty() {
        //Cache is no longer empty
    }

    func cacheIsEmpty() {
        // Cache is empty
    }
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
@interface ViewController () <AATBannerCacheDelegate, AATBannerCacheStatusDelegate>
@property AATBannerCache *bannerCache;
@end

@implementation ViewController

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // [IMPORTANT] Notify AATKit about the currently active view controller
    [AATSDK controllerViewDidAppearWithController:self];

    // Create banner cache configuration instance
    AATBannerCacheConfiguration *configuration = [[AATBannerCacheConfiguration alloc] initWithPlacementName:@"<PLACEMENT_NAME>" size:1];
    configuration.delegate = self;
    
    // Create the banner request instance
    AATBannerRequest *request = [[AATBannerRequest alloc] initWithDelegate:self];
    // Configure request banner sizes
    NSSet *sizes = [[NSSet alloc] initWithArray:@[@(AATBannerSizeBanner320x53), @(AATBannerSizeBanner300x250), @(AATBannerSizeBanner320x100)]];
    [request setRequestBannerSizes:sizes];
    // Configure request targeting information
    request.targetingInformation = @{@"Key": @[@"value"]};
    // Configure request content targeting URL
    request.contentTargetingUrl = @"http://example.com/similar/content";
    // OR
    request.multiContentTargetingUrls = @[@"URL1", @"URL2"];
    // Set configuration banner request
    configuration.requestConfiguration = request;

    // Create the banner cache (once it has been created, it would start loading automatically)
    self.bannerCache = [AATSDK createBannerCacheWithConfiguration:configuration];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    // Destroy the banner cache when it's not needed anymore
    [self.bannerCache destroy];

    // [IMPORTANT] Remove the currently active view controller
    [AATSDK controllerViewWillDisappear];
}

#pragma mark - AATBannerCacheDelegate
- (void)firstBannerLoaded {
    UIView *bannerView = [self.bannerCache consumeWithForce:NO];
    if (bannerView == nil) {
        NSLog(@"An error occurred");
        return;
    }
    // Change bannerView frame (or constraints) to the desired location on the screen
}

#pragma mark - AATBannerCacheStatusDelegate
- (void)cacheIsNoLongerEmpty {
    // Cache is no longer empty
}

- (void)cacheIsEmpty {
    // Cache is empty
}
@end
```

{% endtab %}
{% endtabs %}
