Skip to content
:docs

Migrate from v5 to v6

This guide explains the configuration changes needed to migrate from Buzzvil iOS SDK v5 to v6.

See the GitHub sample code for examples of actual implementations.

Getting started

Requirements

  1. Review the updated requirements for Buzzvil SDK v6 below and apply them to your project settings.

Requirements

  • deployment target
    • Minimum supported: iOS 13 or later
    • Recommended: iOS 14 or later
  • Xcode 16.0 or later

Obtain integration IDs

Feed (BenefitHub) has become web-based BenefitHub. The Feed Unit ID is no longer used directly in integration code.

You can continue using your existing App ID, Native Unit ID, and Interstitial Unit ID.

Integrate a reward server

With the addition of Lucky Box and Mission Pack, you must handle the request parameters described in the postback integration guide.

Install the SDK

Swift Package Manager

Follow these steps to import the Swift package.

  1. In Xcode, go to File > Add Package Dependencies.

  2. Search for the Buzzvil SDK Swift Package GitHub repository.

Code
https://github.com/Buzzvil/buzzvil-ios-sdk
  1. Select a version. We recommend Up to Next Minor Version.

  2. Select BuzzvilSDK from the package products.

For details about adding package dependencies, see the official Apple Developer documentation.

Cocoapods

To install the Buzzvil SDK using CocoaPods, add BuzzvilSDK to your Podfile.

Code
   pod 'BuzzvilSDK', '~> 6.8.0'
Reference — Previous code (BuzzAdBenefit SDK v5)
actionscript3
pod 'BuzzAdBenefit', '= 5.31.3'

Initialize the SDK

Initialize BuzzvilSDK

The constructor parameter of BuzzBenefitConfig.Builder has been renamed from appID to appId.

Swift
import BuzzvilSDK

let config = BuzzBenefitConfig.Builder(appId: "YOUR_APP_ID")
    .build()
BuzzBenefit.shared.initialize(with: config)
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import BuzzvilSDK

let config = BuzzBenefitConfig.Builder(appID: "YOUR_APP_ID")
    .build()
BuzzBenefit.shared.initialize(with: config)

Configure dark mode

Dark mode is now configured through server settings rather than code. Remove the previous dark-mode-related code.

Dark mode optionDescription
BuzzBenefitUserInterfaceStyleLightUses light mode regardless of the system's dark mode setting.
BuzzBenefitUserInterfaceStyleDarkUses dark mode regardless of the system's dark mode setting.
BuzzBenefitUserInterfaceStyleSystemThe SDK's default dark mode setting (기본 값). Uses the system's dark mode setting.

Remove the functions previously used to configure dark mode.

Swift
import BuzzvilSDK

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    // ...생략...
    BuzzBenefit.shared.setUserInterfaceStyle(.system) // 삭제 처리
    return true
  }
}

Log in

No changes.

BenefitHub

Integration

Initialize BenefitHub

Registration with BuzzBenefitConfig using BZVFeedConfig has been removed. The setDefaultFeedConfig function in BuzzBenefitConfig has also been removed, so remove the related code.

Swift
import BuzzvilSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        let config = BuzzBenefitConfig.Builder(appId: "YOUR_APP_ID")
          .build()
        BuzzBenefit.shared.initialize(with: config)
        return true
    }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import BuzzvilSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        let feedConfig = BZVFeedConfig { builder in
            builder.unitID = "YOUR_FEED_UNIT_ID"
        }
        let config = BuzzBenefitConfig.Builder("YOUR_APP_ID")
            .setDefaultFeedConfig(feedConfig)
            .build()
        BuzzBenefit.shared.initialize(with: config)
        return true
    }
}

Display BenefitHub

The previous BZVBuzzAdFeed object has been renamed BuzzBenefitHub. Use the renamed object to display BenefitHub.

Retrieving the ViewController and using it as a child view controller is still supported.

Swift
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
benefitHub.show(on: yourViewController)
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
/** 참고 - 변경 전 코드(BuzzAdBenefit v5) **/

let yourViewController = UIViewController()
let buzzAdFeed = BZVBuzzAdFeed { _ in }
buzzAdFeed.show(on: yourViewController)

Display BenefitHub with a non-default configuration

Displaying BenefitHub with a non-default configuration has been removed. Declare a BuzzBenefitHub object to display BenefitHub. Remove the associated BZVFeedConfig code.

Lucky Box

You can now open Lucky Box directly through the BenefitHub object. The code for opening Lucky Box directly has changed.

Swift
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
let benefitHubConfig = BuzzBenefitHubConfig.Builder()
  .setQueryParams(BuzzBenefitHubPage.luckyBox.toRedirectQueryParams())
  .build()
benefitHub.setConfig(benefitHubConfig)
benefitHub.show(on: yourViewController)
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
/** 참고 - 변경 전 코드(BuzzAdBenefit v5) **/
let yourViewController = UIViewController()
let feedConfig = BZVFeedConfig { builder in
  builder.unitID = "BENEFIT_HUB_UNIT_ID"
  builder.initialNavigationPage = .luckyBox
}
let buzzAdFeed = BZVBuzzAdFeed(block: { builder in
  builder.config = feedConfig
})

Mission Pack

You can now open Mission Pack directly through the BenefitHub object. The code for opening Mission Pack directly has changed.

Swift
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
let benefitHubConfig = BuzzBenefitHubConfig.Builder()
  .setQueryParams(BuzzBenefitHubPage.missionPack.toRedirectQueryParams())
  .build()
benefitHub.setConfig(benefitHubConfig)
benefitHub.show(on: yourViewController)
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
/** 참고 - 변경 전 코드(BuzzAdBenefit v5) **/
let yourViewController = UIViewController()
let feedConfig = BZVFeedConfig { builder in
  builder.unitID = "BENEFIT_HUB_UNIT_ID"
  builder.initialNavigationPage = .missionPack
}
let buzzAdFeed = BZVBuzzAdFeed(block: { builder in
  builder.config = feedConfig
})

Reward history

A new page displays reward history, which was previously unavailable. You can also open it directly without going through BenefitHub.

Swift
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
let benefitHubConfig = BuzzBenefitHubConfig.Builder()
  .setQueryParams(BuzzBenefitHubPage.history.toRedirectQueryParams())
  .build()
benefitHub.setConfig(benefitHubConfig)
benefitHub.show(on: yourViewController)

Implement entry paths in your app UI

Features related to BZVFeedEntryView have been removed. Update your implementation to open BenefitHub through BuzzBenefitHub, and remove code that uses BZVFeedEntryView.

Display available reward points

The availableReward feature provided through BZVBuzzAdFeed has been removed. BZVBuzzAdFeed.load() has also been removed, so remove the related code.

Additional features

Integrate BenefitHub as a child view controller

The functionality remains the same, but the class name has changed. Update your code accordingly.

Swift
import BuzzvilSDK

final class ContainerViewController: UIViewController {
  let benefitHub = BuzzBenefitHub()

  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .systemBackground

    displayContentViewController(benefitHub.getViewController())
  }
  
  private func displayContentViewController(_ contentViewController: UIViewController) {
    addChild(contentViewController)
    contentViewController.view.frame = view.bounds
    view.addSubview(contentViewController.view)
    contentViewController.didMove(toParent: self)
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import BuzzvilSDK

final class ContainerViewController: UIViewController {
  let buzzAdFeed = BZVBuzzAdFeed { builder in }

  override func viewDidLoad() {
    super.viewDidLoad()
    displayContentViewController(buzzAdFeed.viewController)
  }

  private func displayContentViewController(_ contentViewController: UIViewController) {
    addChild(contentViewController)
    contentViewController.view.frame = view.bounds
    view.addSubview(contentViewController.view)
    contentViewController.didMove(toParent: self)
  }
}

Native

Integration

Step 1. Prepare

No changes.

Step 2. Configure the ad layout

The functionality is almost unchanged, but the class names have changed.

BZVMediaView -> BuzzMediaView BZVDefaultCtaView -> BuzzDefaultCtaView BZVNativeAd2View -> BuzzNativeAdView BZVNativeAd2ViewBinder -> BuzzNativeViewBinder

The UnitID value has also moved from the constructor of BuzzNativeViewBinder.Builder() to BuzzNative.

BZVNativeToFeedView, which served as a BenefitHub entry point, has been removed. Remove the related code.

Swift
import UIKit
import BuzzvilSDK

final class ViewController: UIViewController {
  private let nativeAdView = BuzzNativeAdView(frame: .zero)
  private let mediaView = BuzzMediaView(frame: .zero)
  private let iconImageView = UIImageView(frame: .zero)
  private let titleLabel = UILabel(frame: .zero)
  private let descriptionLabel = UILabel(frame: .zero)
  private let ctaView = BuzzDefaultCtaView(frame: .zero)

  private lazy var viewBinder = BuzzNativeViewBinder.Builder()
    .nativeAdView(nativeAdView)
    .mediaView(mediaView)
    .iconImageView(iconImageView)
    .titleLabel(titleLabel)
    .descriptionLabel(descriptionLabel)
    .ctaView(ctaView)
    .build()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    self.view.addSubview(nativeAdView)
    nativeAdView.addSubview(mediaView)
    nativeAdView.addSubview(iconImageView)
    nativeAdView.addSubview(titleLabel)
    nativeAdView.addSubview(descriptionLabel)
    nativeAdView.addSubview(ctaView)

    // AutoLayout Constraints 설정 
    // ...
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

final class ViewController: UIViewController {
  private let nativeAd2View = BZVNativeAd2View(frame: .zero)
  private let mediaView = BZVMediaView(frame: .zero)
  private let iconImageView = UIImageView(frame: .zero)
  private let titleLabel = UILabel(frame: .zero)
  private let descriptionLabel = UILabel(frame: .zero)
  private let ctaView = BZVDefaultCtaView(frame: .zero)
  private let nativeToFeedView = BZVNativeToFeedView(frame: .zero)

  private lazy var viewBinder = BZVNativeAd2ViewBinder
    .Builder(unitId: "YOUR_NATIVE_UNIT_ID")
    .nativeAd2View(nativeAd2View)
    .mediaView(mediaView)
    .iconImageView(iconImageView)
    .titleLabel(titleLabel)
    .descriptionLabel(descriptionLabel)
    .ctaView(ctaView)
    .build()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    self.view.addSubview(nativeAd2View)
    nativeAd2View.addSubview(mediaView)
    nativeAd2View.addSubview(iconImageView)
    nativeAd2View.addSubview(titleLabel)
    nativeAd2View.addSubview(descriptionLabel)
    nativeAd2View.addSubview(ctaView)

    self.view.addSubView(nativeToFeedView)
    nativeToFeedView.setUnitId("YOUR_NATIVE_UNIT_ID")

    // AutoLayout Constraints 설정 
    // ...
  }
}

Step 3. Display ads

The BZVNativeAd2ViewBinder.bind() function used for ad allocation has been replaced by BuzzNative.load(). Ads allocated by BuzzNative are now displayed through ViewBinder. Update your ad allocation code accordingly.

Swift
final class ViewController: UIViewController {
  private lazy var native = BuzzNative(unitId: "YOUR_NATIVE_UNIT_ID")

  private lazy var viewBinder = BuzzNativeViewBinder.Builder()
    .nativeAdView(nativeAdView)
    .mediaView(mediaView)
    .iconImageView(iconImageView)
    .titleLabel(titleLabel)
    .descriptionLabel(descriptionLabel)
    .ctaView(ctaView)
    .build()

  override func viewDidLoad() {
    // Warning: retain cycle 방지를 위해 closure 내에서 반드시 weak self를 사용해주세요.
    native.subscribeRefreshEvents(
      onRequest: { [weak self] in
        // 광고 갱신 할당을 요청한 상태입니다.
        // 이후에는 onSuccess, onFailure 중 하나가 호출됩니다.
        // 광고 자동 갱신을 시도할 때마다 반복적으로 호출됩니다.
      }, 
      onSuccess: { [weak self] nativeAd in
        // 광고 갱신 할당에 성공하면 호출됩니다.
      }, 
      onFailure: { [weak self] error in
        // 더 이상 갱신할 수 있는 광고가 없을 때 호출됩니다.
      }
    )

    // 광고 할당을 수행합니다.
    native.load(
      onSuccess: { [weak self] nativeAd in
        // 초기 광고 할당에 성공하면 호출됩니다.
      }, 
      onFailure: { [weak self] error in
        // 초기 광고 할당에 실패하면 호출됩니다.
      }
    )

    // 할당된 광고 표시를 자동으로 수행합니다.
    viewBinder.bind(native)
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
final class ViewController: UIViewController {
  // ...생략...
  private let activityIndicatorView = UIActivityIndicatorView(frame: .zero)

  override func viewDidLoad() {
    // ...생략...

    // Warning: retain cycle 방지를 위해 closure 내에서 반드시 weak self를 사용해주세요.
    viewBinder.subscribeEvents(onRequest: { [weak self] in
      // 광고 할당을 요청한 상태입니다.
      // 이후에는 onNext, onCompleted, onError 중 하나가 호출됩니다.
      // 광고 자동 갱신을 시도할 때마다 반복적으로 호출됩니다.
      // 로딩 화면 등을 구현할 수 있습니다.
      self?.activityIndicatorView.startAnimating()
    }, onNext: { [weak self] nativeAd2 in
      // 광고 할당에 성공하면 호출됩니다.
      // 이후에 광고 갱신 시 onRequest가 다시 호출됩니다.
      // 광고 자동 갱신을 성공할 때마다 반복적으로 호출됩니다.
      // 로딩 화면 등을 구현한 경우, 여기에서 로딩을 종료합니다.
      self?.activityIndicatorView.stopAnimating()
    }, onError: { [weak self] error in
      // 최초 광고 할당에 실패하면 호출됩니다.
      // 로딩 화면 등을 구현한 경우, 여기에서 로딩을 종료합니다.
      self?.activityIndicatorView.stopAnimating()
      // NativeAd2View를 숨기거나, Error UI로 대체할 수 있습니다.
      print("Failed to load ad by \(error.localizedDescription).")
    }, onCompleted: { [weak self] in
      // 더 이상 갱신할 수 있는 광고가 없을 때 호출됩니다.
      // 로딩 화면 등을 구현한 경우, 여기에서 로딩을 종료합니다.
      self?.activityIndicatorView.stopAnimating()
    })

    // 광고 할당 및 표시를 자동으로 수행합니다.
    viewBinder.bind()
  }
}
Display the base reward amount

Displaying base rewards in advance has been removed. The BuzzAdBenefit.getAvailableFeedBaseReward() function has also been removed, so remove the related code.

Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
BuzzAdBenefit.getAvailableFeedBaseReward(for: YOUR_FEED_UNIT_ID) { [weak self] (reward) in
  guard let self = self else { return }
  if reward > 0 {
    self.nativeToFeedLabel.text = "\(reward) 포인트 받고 더 많은 참여 기회 보기"
  } else {
    self.nativeToFeedLabel.text = "더 많은 참여 기회 보기"
  }
}

Additional features

Register a video ad listener

Video ad listeners have been removed because native placements do not provide video ads. The BZVNativeAdViewVideoDelegate protocol has been removed; remove the related code.

Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

final class ViewController: UIViewController {
  private let nativeAd2View = BZVNativeAd2View(frame: .zero)
  // ...생략...

  override func viewDidLoad() {
    // ...생략...
    nativeAd2View.videoDelegate = self
  }
}

// MARK: BZVNativeAdViewVideoDelegate
extension ViewController: BZVNativeAdViewVideoDelegate {
  func bzvNativeAdView(_ nativeAdView: BZVNativeAdView, willStartPlayingVideoAd nativeAd: BZVNativeAd) {
    // 비디오 광고의 비디오가 시작하기 직전에 호출됩니다.
  }

  func bzvNativeAdView(_ nativeAdView: BZVNativeAdView, didResumeVideoAd nativeAd: BZVNativeAd) {
    // 비디오 광고의 비디오가 재생되면 호출됩니다.
  }

  func bzvNativeAdView(_ nativeAdView: BZVNativeAdView, willReplayVideoAd nativeAd: BZVNativeAd) {
    // 비디오 광고의 비디오가 리플레이되면 호출됩니다.
  }

  func bzvNativeAdView(_ nativeAdView: BZVNativeAdView, didPauseVideoAd nativeAd: BZVNativeAd) {
    // 비디오 광고의 비디오가 일시정지되면 호출됩니다.
  }

  func bzvNativeAdView(_ nativeAdView: BZVNativeAdView, didFinishPlayingVideoAd nativeAd: BZVNativeAd) {
    // 비디오 광고의 비디오가 종료되면 호출됩니다.
  }
}

Register an ad event listener

Ad events previously received through BZVNativeAd2ViewBinder are now received through the BuzzNative object. Update your code accordingly.

Swift
final class ViewController: UIViewController {
  // ...생략...

  override func viewDidLoad() {
    // ...생략...

    // Native 광고 이벤트 처리를 위한 closure를 등록하고 각 이벤트에 따라 필요한 기능을 구현합니다.
    // Warning: retain cycle 방지를 위해 closure 내에서 반드시 weak self를 사용해주세요.
    native.subscribeAdEvents(onImpressed: { [weak self] nativeAd in
      // Native 광고가 유저에게 노출되었을 때 호출됩니다.
    }, onClicked: { [weak self] nativeAd in
      // 유저가 Native 광고를 클릭했을 때 호출됩니다.
    }, onRewardRequested: { [weak self] nativeAd in
      // 리워드 적립 요청시에 호출됩니다.
    }, onRewarded: { [weak self] nativeAd, rewardResult in
      // 리워드 적립 결과를 수신했을 때 호출됩니다.
    }, onParticipated: { [weak self] nativeAd in
      // 광고 참여가 완료되었을 때 호출됩니다.
    })

    // ...생략...
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
final class ViewController: UIViewController {
  // ...생략...

  override func viewDidLoad() {
    // ...생략...

    // Native 광고 이벤트 처리를 위한 closure를 등록하고 각 이벤트에 따라 필요한 기능을 구현합니다.
    // 로그 기록, 단순 알림 외에 다른 동작을 추가하는 것을 권장하지 않습니다. 자동 갱신 등 네이티브 2.0의 기능과 직접 구현한 동작이 충돌할 수 있습니다.
    // Warning: 반드시 bind 함수를 호출하기 전에 호출해야 해야합니다.
    // Warning: retain cycle 방지를 위해 closure 내에서 반드시 weak self를 사용해주세요.
    viewBinder.subscribeAdEvents(onImpressed: { [weak self] nativeAd2 in
      // Native 광고가 유저에게 노출되었을 때 호출됩니다.
    }, onClicked: { [weak self] nativeAd2 in
      // 유저가 Native 광고를 클릭했을 때 호출됩니다.
    }, onRewardRequested: { [weak self] nativeAd2 in
      // 리워드 적립 요청시에 호출됩니다.
    }, onRewarded: { [weak self] nativeAd2, rewardResult in
      // 리워드 적립 결과를 수신했을 때 호출됩니다.
    }, onParticipated: { [weak self] nativeAd2 in
      // 광고 참여가 완료되었을 때 호출됩니다.
    })

    viewBinder.bind()
  }
}

Reward results (BZVRewardResult)

The class has been renamed from BZVRewardResult to BuzzRewardResult. See Reward result types (BuzzRewardResult).

Implement a carousel

Implement basic carousel features
Step 1. Allocate ads

The classes and functions have changed. Update your code using the table below.

AS-ISTO-BE
BZVNativeAd2PoolBuzzNativeGroup
BZVNativeAd2Pool.loadAds()BuzzNativeGroup.load()
completionHandleronSuccess
errorHandleronFailure
Swift
import UIKit
import BuzzvilSDK

final class CarouselViewController: UIViewController {
  private let unitId = "YOUR_UNIT_ID"
  
  // 최대 10개의 광고를 요청할 수 있습니다.
  private let adRequestCount = 5

  // 실제 할당받은 광고의 개수입니다. 
  // 이 값은 collectionView datasource의 collectionView(_:numberOfItemsInSection:) 함수의 return 값으로 사용합니다.
  private var loadedAdCount = 0

  // 광고 중복 할당을 막기 위해 하나의 캐러셀에 하나의 BuzzNativeGroup 인스턴스를 생성하여 사용합니다.
  private lazy var nativeGroup = BuzzNativeGroup(unitId: unitId)

  override func viewDidLoad() {
    super.viewDidLoad()
    setupCarousel()
  }

  private func setupCarousel() {
    // BuzzNativeGroup에 광고 할당을 요청합니다.
    nativeGroup.load(
      count: adRequestCount,
      onSuccess: { [weak self] adCount in
        // 실제로 할당받은 광고의 개수(count)를 업데이트합니다.
        self?.loadedAdCount = adCount
      },
      onFailure: { [weak self] error in
        // 광고 할당 실패 시 발생하는 NSError 오류 코드에 대한 자세한 내용은 오류 코드가 나타납니다 토픽을 참고하세요.
      }
    )
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

final class CarouselViewController: UIViewController {
  private let unitID = "YOUR_UNIT_ID"
  
  // 최대 10개의 광고를 요청할 수 있습니다.
  private let adRequestCount = 5

  // 실제 할당받은 광고의 개수입니다. 
  // 이 값은 collectionView datasource의 collectionView(_:numberOfItemsInSection:) 함수의 return 값으로 사용합니다.
  private var loadedAdCount = 0

  // 광고 중복 할당을 막기 위해 하나의 캐러셀에 하나의 NativeAd2Pool 인스턴스를 생성하여 사용합니다.
  private lazy var pool = BZVNativeAd2Pool(unitId: unitId)

  override func viewDidLoad() {
    super.viewDidLoad()
    setupCarousel()
  }

  private func setupCarousel() {
    // BZVNativeAd2Pool에 광고 할당을 요청합니다.
    pool.loadAds(count: adRequestCount) { [weak self] adCount in
      // 실제로 할당받은 광고의 개수(adCount)를 업데이트합니다.
      self?.loadedAdCount = adCount
    } errorHandler: { [weak self] error in
      // 광고 할당 실패 시 발생하는 NSError 오류 코드에 대한 자세한 내용은 오류 코드가 나타납니다 토픽을 참고하세요.
    }
  }
}
Step 2. Implement UICollectionViewCell

In your existing UICollectionViewCell, replace the implementation using setPoool() with bind(with native: BuzzNative). Pass the BuzzNative object to the UICollectionViewCell and add the necessary code.

Swift
final class CarouselCell: UICollectionViewCell {
  // ...

  private lazy var viewBinder = BuzzNativeViewBinder.Builder()
    .nativeAdView(nativeAdView)
    .mediaView(mediaView)
    .iconImageView(iconImageView)
    .titleLabel(titleLabel)
    .descriptionLabel(descriptionLabel)
    .ctaView(ctaView)
    .build()
  
  // ...

  override func prepareForReuse() {
    super.prepareForReuse()
    // prepareForReuse 내에서 unbind를 반드시 호출하여 cell을 재사용할 때 문제가 발생하지 않게 합니다.
    viewBinder.unbind()
  }

  // collectionView의 collectionView(_:cellForItemAt:) 시점에 호출합니다.
  func bind(with native: BuzzNative) {
   // bind()를 호출하면 할당된 광고 표시 및 갱신이 자동으로 수행됩니다.
    viewBinder.bind(native)
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
final class CarouselCell: UICollectionViewCell {
  // ...

  private lazy var viewBinder = BZVNativeAd2ViewBinder
    .Builder(unitId: "YOUR_NATIVE_UNIT_ID")
    .nativeAd2View(nativeAd2View)
    .mediaView(mediaView)
    .iconImageView(iconImageView)
    .titleLabel(titleLabel)
    .descriptionLabel(descriptionLabel)
    .ctaView(ctaView)
    .build()
  
  // ...

  override func prepareForReuse() {
    super.prepareForReuse()
    // prepareForReuse 내에서 unbind를 반드시 호출하여 cell을 재사용할 때 문제가 발생하지 않게 합니다.
    viewBinder.unbind()
  }

  // collectionView의 collectionView(_:cellForItemAt:) 시점에 호출합니다.
  func setPool(with pool: BZVNativeAd2Pool, for adKey: Int) {
    // 해당 index(adKey)에 해당하는 NativeAd2ViewBinder가 NativeAd2Pool을 사용하도록 합니다.
    viewBinder.setPool(pool, at: adKey)
  }

  // collectionView의 collectionView(_:cellForItemAt:) 시점에 호출합니다.
  func bind() {
    // NativeAd2ViewBinder의 bind()를 호출하면 광고 할당 및 갱신이 자동으로 수행됩니다.
    viewBinder.bind()
  }
}
BenefitHub entry slide

This feature has been removed along with BZVFeedPromotionView and BZVFeedPromotionViewBinder. Remove them from your code. Also remove FeedPromitionCell from the previous guide.

Open BenefitHub

The BZVFeedEntryView class used as a BenefitHub entry point has been removed. Replace it with code that opens BenefitHub, as shown below.

Swift
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
benefitHub.show(on: yourViewController)
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

final class CarouselFeedEntryView: BZVFeedEntryView {
  private lazy var button: UIButton = {
    let button = UIButton(type: .system)
    button.setTitle("포인트 더 받으러 가기", for: .normal)
    button.tintColor = .systemBlue
    return button
  }()
  
  override init(frame: CGRect) {
    super.init(frame: frame)
    setupView()
    setupLayout()
  }
  
  required init?(coder: NSCoder) {
    fatalError()
  }
  
  private func setupView() {
    addSubview(button)
    clickableViews = [button]
  }
  
  private func setupLayout() {
    button.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      button.topAnchor.constraint(equalTo: topAnchor),
      button.leadingAnchor.constraint(equalTo: leadingAnchor),
      button.trailingAnchor.constraint(equalTo: trailingAnchor),
      button.bottomAnchor.constraint(equalTo: bottomAnchor),
    ])
  }
}
Implement optional carousel features
Implement a loading screen

The previously separate function has moved into bind(with native: BuzzNative) in the UICollectionViewCell.

Swift
final class CarouselCell: UICollectionViewCell {
  // ...
  
  private lazy var activityIndicatorView: UIActivityIndicatorView = {
    let indicator = UIActivityIndicatorView(frame: .zero)
    indicator.hidesWhenStopped = true
    return indicator
  }()
  
  override init(frame: CGRect) {
    super.init(frame: frame)
    setupView()
    setupLayout()
  }
  
  private func setupView() {
    // ...
    contentView.addSubview(activityIndicatorView)
  }
  
  private func setupLayout() {
    // ...
    
    activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor),
      activityIndicatorView.centerYAnchor.constraint(equalTo: centerYAnchor),
    ])
  }
  
  func bind(with native: BuzzNative) {
    native.subscribeRefreshEvents(
      onRequest: { [weak self] in
        self?.activityIndicatorView.startAnimating()
        self?.nativeAdView.alpha = 0.5
      },
      onSuccess: { [weak self] _ in
        self?.activityIndicatorView.stopAnimating()
        self?.nativeAdView.alpha = 1
      },
      onFailure: { [weak self] error in
        self?.activityIndicatorView.stopAnimating()
        self?.nativeAdView.alpha = 1
      },
    )

    viewBinder.bind(native: native)
  }
}

extension CarouselViewController: UICollectionViewDataSource {
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // ...
    cell.bind(with: native)
    return cell
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
final class CarouselCell: UICollectionViewCell {
  // ...
  
  private lazy var activityIndicatorView: UIActivityIndicatorView = {
    let indicator = UIActivityIndicatorView(frame: .zero)
    indicator.hidesWhenStopped = true
    return indicator
  }()
  
  override init(frame: CGRect) {
    super.init(frame: frame)
    setupView()
    setupLayout()
  }
  
  private func setupView() {
    // ...
    contentView.addSubview(activityIndicatorView)
  }
  
  private func setupLayout() {
    // ...
    
    activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor),
      activityIndicatorView.centerYAnchor.constraint(equalTo: centerYAnchor),
    ])
  }
  
  func setupLoading() {
    viewBinder.subscribeEvents(onRequest: { [weak self] in
      self?.activityIndicatorView.startAnimating()
      self?.nativeAd2View.alpha = 0.5
    }, onNext: { [weak self] _ in
      self?.activityIndicatorView.stopAnimating()
      self?.nativeAd2View.alpha = 1
    }, onError: { [weak self] in
      self?.activityIndicatorView.stopAnimating()
      self?.nativeAd2View.alpha = 1
      print("error: \($0)")
    }, onCompleted: { [weak self] in
      self?.activityIndicatorView.stopAnimating()
      self?.nativeAd2View.alpha = 1
      print("completed")
    })
  }
}

extension CarouselViewController: UICollectionViewDataSource {
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // ...
    cell.setupLoading()
    cell.setPool(with: pool, for: indexPath.item)
    cell.bind()
    return cell
  }
}
Register an ad event listener

The function and its location have changed: it is now inside bind(). The previously separate function has moved into bind(with native: BuzzNative) in the UICollectionViewCell. Register it through a BuzzNative object instead of the previous BZVNativeAd2ViewBinder class.

Swift
final class CarouselCell: UICollectionViewCell {
  // ...
  
  func bind(with native: BuzzNative) {
    // ...

    native.subscribeAdEvents(
      onImpressed: { [weak self] in
        print("impressed: \($0.title)")
      }, 
      onClicked: { [weak self] in
        print("clicked: \($0.title)")
      }, 
      onRewardRequested: { [weak self] in
        print("requested reward: \($0.title)")
      }, 
      onRewarded: { [weak self] in
        print("received reward result: \($0.title), \($1)")
      }, 
      onParticipated: { [weak self] in
        print("participated: \($0.title)")
      }
    )

    // ...
  }
}

extension CarouselViewController: UICollectionViewDataSource {
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // ...
    cell.bind(with: native)
    return cell
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
final class CarouselCell: UICollectionViewCell {
  // ...
  
  func setupEventListeners() {
    viewBinder.subscribeAdEvents(onImpressed: { [weak self] in
      print("impressed: \($0.title)")
    }, onClicked: { [weak self] in
      print("clicked: \($0.title)")
    }, onRewardRequested: { [weak self] in
      print("requested reward: \($0.title)")
    }, onRewarded: { [weak self] in
      print("received reward result: \($0.title), \($1)")
    }, onParticipated: { [weak self] in
      print("participated: \($0.title)")
    })
  }
}

extension CarouselViewController: UICollectionViewDataSource {
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // ...
    cell.setupEventListeners()
    cell.setPool(with: pool, for: indexPath.item)
    cell.bind()
    return cell
  }
}

Interstitial

Integration

Step 1. Prepare

No changes.

Step 2. Allocate and display ads

The class names and protocols have changed. Update your code using the examples below.

The interstitial object has changed from BZVBuzzAdInterstitial to BuzzInterstitial. Initialization of BuzzInterstitial has changed. Update your code as shown below. The delegate protocol has changed from BZVBuzzAdInterstitialDelegate to BuzzInterstitialDelegate.

Swift
import UIKit
import BuzzvilSDK

final class ViewController: UIViewController, BuzzInterstitialDelegate {
  let buzzAdInterstitial = BuzzInterstitial(unitId: "YOUR_INTERSTITIAL_UNIT_ID", type: .dialog)

  override func viewDidLoad() {
    super.viewDidLoad()

    buzzAdInterstitial.delegate = self
    buzzAdInterstitial.load()
  }
}
extension ViewController: BuzzInterstitialDelegate {
  func BuzzInterstitialDidLoadAd(_ interstitial: BuzzInterstitial) {
    // 할당된 광고가 있으면 호출됩니다.
    // Interstitial 광고를 화면에 표시합니다.
    interstitial.present(on: self)
  }
  
  func BuzzInterstitialDidFail(toLoadAd interstitial: BuzzInterstitial, withError error: Error) {
    // 할당된 광고가 없으면 호출됩니다.
  }
  
  func BuzzInterstitialDidDismiss(_ viewController: UIViewController) {
    // Interstitial 지면이 종료되면 호출됩니다.
    // 필요에 따라 추가 기능을 구현하세요.
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

final class ViewController: UIViewController, BZVBuzzAdInterstitialDelegate {
  let buzzAdInterstitial = BZVBuzzAdInterstitial { builder in
    builder.unitId = "YOUR_INTERSTITIAL_UNIT_ID"
    builder.type = .dialog
  }

  override func viewDidLoad() {
    super.viewDidLoad()

    buzzAdInterstitial.delegate = self
    buzzAdInterstitial.load()
  }
}
extension ViewController: BZVBuzzAdInterstitialDelegate {
  func bzvBuzzAdInterstitialDidLoadAd(_ interstitial: BZVBuzzAdInterstitial) {
    // 할당된 광고가 있으면 호출됩니다.
    // Interstitial 광고를 화면에 표시합니다.
    interstitial.present(on: self)
  }
  
  func bzvBuzzAdInterstitialDidFail(toLoadAd interstitial: BZVBuzzAdInterstitial, withError error: Error) {
    // 할당된 광고가 없으면 호출됩니다.
  }
  
  func bzvBuzzAdInterstitialDidDismiss(_ viewController: UIViewController) {
    // Interstitial 지면이 종료되면 호출됩니다.
    // 필요에 따라 추가 기능을 구현하세요.
  }
}

Step 3. Add a BenefitHub entry point to the interstitial

The option to add a button that opens BenefitHub from an interstitial has changed. The entry point is now always visible instead of optional. Remove the existing buzzAdBenefitRouter code.

Swift
let feedConfig = BZVFeedConfig { builder in
  builder.unitID = "YOUR_FEED_UNIT_ID"
}

let buzzAdInterstitial = BZVBuzzAdInterstitial { builder in
  builder.unitId = "YOUR_INTERSTITIAL_UNIT_ID"
  builder.type = .dialog
  builder.buzzAdBenefitRouter = BuzzBenefitRouterFactory.createFeedRouter(feedConfig) // 삭제 처리
}

BuzzBanner

The class names have changed. Review the changes below and update them accordingly.

AS-ISTO-BE
BuzzAdBenefitBannerViewBuzzBannerSize
BuzzAdBenefitBannerSizeBuzzBannerView
BuzzAdBenefitBannerViewDelegateBuzzBannerViewDelegate
Swift
import UIKit
import BuzzvilSDK

final class ViewController: UIViewController {
  private lazy var bannerView: BuzzBannerView = {
    let bannerView = BuzzBannerView(frame: .zero)
    bannerView.delegate = self
    return bannerView
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    let config = BuzzBannerConfig.Builder(placementId: placementID)
      .setSize(.w320h50)
      .build()
    bannerView.setConfig(rootViewController: self, config: config)

    view.addSubview(bannerView)

    // ...
  }

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    bannerView.requestAd()
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    bannerView.removeAd()
  }
}

extension ViewController: BuzzBannerViewDelegate {
  func bannerView(_ bannerView: BuzzBannerView, didLoadApid: String) {
    // Banner에 광고가 할당 되었을 때 호출 됩니다.
  }
  
  func bannerView(_ bannerView: BuzzBannerView, didFailApid: String, error: NSError) {
    // Banner에 광고 할당이 실패했을 때 호출 됩니다.
  }
  
  func bannerView(_ bannerView: BuzzBannerView, didClickApid: String) {
    // Banner가 클릭되었을 때 호출 됩니다.
  }
  
  func bannerView(_ bannerView: BuzzBannerView, didRemoveApid: String) {
    // Banner가 제거되었을 떄 호출 됩니다.
  }
}
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

final class ViewController: UIViewController {
  private lazy var bannerView: BuzzAdBenefitBannerView = {
    let bannerView = BuzzAdBenefitBannerView(frame: .zero)
    bannerView.delegate = self
    return bannerView
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    let config = BuzzAdBenefitBannerConfig.Builder(placementID: placementID)
      .setSize(.w320h50)
      .build()
    bannerView.setConfig(rootViewController: self, config: config)

    view.addSubview(bannerView)

    // ...
  }

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    bannerView.requestAd()
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    bannerView.removeAd()
  }
}

extension ViewController: BuzzAdBenefitBannerViewDelegate {
  func bannerView(_ bannerView: BuzzAdBenefitBannerView, didLoadApid: String) {
    // Banner에 광고가 할당 되었을 때 호출 됩니다.
  }
  
  func bannerView(_ bannerView: BuzzAdBenefitBannerView, didFailApid: String, error: NSError) {
    // Banner에 광고 할당이 실패했을 때 호출 됩니다.
  }
  
  func bannerView(_ bannerView: BuzzAdBenefitBannerView, didClickApid: String) {
    // Banner가 클릭되었을 때 호출 됩니다.
  }
  
  func bannerView(_ bannerView: BuzzAdBenefitSDK.BuzzAdBenefitBannerView, didRemoveApid: String) {
    // Banner가 제거되었을 떄 호출 됩니다.
  }
}

UI configuration

Most theme-related code has been removed; only custom CTA button implementation remains. Remove the other color-related code. To configure the primary color through server settings, contact your Buzzvil representative at help@buzzvil.com.

Implement a custom CTA button

The protocol required to implement a custom CTA button has been renamed. BZVCtaViewProtocol -> BuzzCtaViewProtocol

Swift
// MARK: BZVCtaViewProtocol
protocol BZVCtaViewProtocol {
  // 리워드가 없는 광고에 대한 CTA 뷰 레이아웃을 정의합니다.
  func renderRewardNotAvailableViewState(withCtaText ctaText: String)

  // 리워드가 있는 광고에 대한 CTA 뷰 레이아웃을 정의합니다.
  func renderRewardAvailableViewState(withCtaText ctaText: String, reward: Int)

  // 참여 확인 중인 광고에 대한 CTA 뷰 레이아웃을 정의합니다.
  func renderParticipatingViewState(withCtaText ctaText: String)

  // 참여 완료한 광고에 대한 CTA 뷰 레이아웃을 정의합니다.
  func renderParticipatedViewState(withCtaText ctaText: String)
}

Custom in-app browser

This version does not support a custom in-app browser. Remove the previous BuzzAdBrowser, BZVLauncher, and BZVLauncherDelegate code.

Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

final class CustomBrowserViewController: UIViewController {
  private lazy var browserViewController: UIViewController = {
    BuzzAdBrowser.sharedInstance().browserViewController()
  }()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    displayContentViewController(browserViewController)
  }

  private func displayContentViewController(_ contentViewController: UIViewController) {
    addChild(contentViewController)
    contentViewController.view.frame = view.bounds
    view.addSubview(contentViewController.view)
    contentViewController.didMove(toParent: self)
  }
}
Swift
import Foundation
import BuzzvilSDK

final class CustomLauncher: NSObject, BZVLauncher {
  // 런처와 관련된 이벤트를 수신할 수 있습니다.
  var delegate: BZVLauncherDelegate?

  func open(with launchInfo: BZVLaunchInfo) {
    // launchInfo의 인자를 확인하여 광고 또는 콘텐츠인지 미리 판단할 수 있습니다.
    if let ad = launchInfo.ad {
      if ad.isDeepLink {
        // 딥링크 광고일 경우 필요한 작업을 할 수 있습니다.
      }
    } else if let article = launchInfo.article {
      let sourceURL = article.sourceURL
    }

    let customBrowserViewController = CustomBrowserViewController()
    YOUR_ROOT_VIEW_CONTROLLER.presentedViewController?.present(customBrowserViewController, animated: true, completion: nil)
  }
}
Swift
let launcher = CustomLauncher()
BuzzAdBenefit.setLauncher(launcher)

Agree to the privacy policy

The functions for checking privacy policy consent and providing consent have changed.

Statusenum
AgreedBuzzPrivacyConsentStatus.granted
DeniedBuzzPrivacyConsentStatus.revoked
Swift
BuzzAdBenefit.shared.loadPrivacyConsentStatus(onSuccess: { [weak self] status in
  // 현재 개인정보 처리 방침 상태를 가져올 수 있습니다
}, onFailure: { [weak self] error in
  // 개인정보 처리방침에 대한 상태를 가져오는데 실패 했을 경우 호출 됩니다.
})

BuzzAdBenefit.shared.grantPrivacyConsent(onSuccess: { [weak self] in
  // 개인정보 처리방침 동의에 성공했을 경우 호출 됩니다.
}, onFailure: { [weak self] error in
  // 개인정보 처리방침 동의 요청에 실패했을 경우 호출 됩니다.
})
Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
let privacyPolicyManager = BuzzAdBenefit.privacyPolicyManager

// 직접 구현한 개인정보 제3자 제공 동의 UI에서 동의를 받았을 경우 아래 코드를 실행하면, 피드 화면에서 개인정보 제3자 제공 동의 UI가 노출되지 않으면서 광고 할당이 정상적으로 진행 됩니다.
// 아래의 코드를 실행하지 않을 경우 피드 진입 시 개인정보 제3자 제공 동의 UI가 노출되기 때문에 필수적으로 실행이 필요합니다.
privacyPolicyManager.grantConsent()

// 아래 코드를 통해서 수집 동의를 철회할 수 있습니다. 이 코드가 실행되면 피드에서 광고 할당이 이루어지지 않습니다.
privacyPolicyManager.revokeConsent()

Mission Pack

The standalone BuzzAdMissionPack class has been removed and merged into BuzzBenefitHub. Remove the related code.

Reference — Previous code (BuzzAdBenefit SDK v5)
Swift
import UIKit
import BuzzvilSDK

class MissionPackViewController: UIViewController {
  let missionPack = BuzzAdBenefitMissionPack(unitId: "YOUR_MISSION_PACK_UNIT_ID")
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    showMissionPack()
  }
  
  // missionPack 사용가능한지 체크하기
  func checkCanOpenMissionPack() {
    missionPack.canOpen {
      print ("MissionPack Can open !")
    } onFailure: { error in
      print ("MissionPack Can't open error: \(error.localizedDescription)")
    }
  }
  
  // missionPack 화면에 표시하기
  func showMissionPack() {
    missionPack.show(on: self, onFailure: { error in
      print ("MissionPack Can't open error: \(error.localizedDescription)")
    })
  }
}