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
- 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.
-
In Xcode, go to
File > Add Package Dependencies. -
Search for the Buzzvil SDK Swift Package GitHub repository.
https://github.com/Buzzvil/buzzvil-ios-sdk
-
Select a version. We recommend Up to Next Minor Version.
-
Select
BuzzvilSDKfrom 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.
pod 'BuzzvilSDK', '~> 6.8.0'
Reference — Previous code (BuzzAdBenefit SDK v5)
pod 'BuzzAdBenefit', '= 5.31.3'
Initialize the SDK
Initialize BuzzvilSDK
The constructor parameter of BuzzBenefitConfig.Builder has been renamed from appID to appId.
import BuzzvilSDK
let config = BuzzBenefitConfig.Builder(appId: "YOUR_APP_ID")
.build()
BuzzBenefit.shared.initialize(with: config)
@import BuzzvilSDK;
BuzzBenefitConfig *config = [BuzzBenefitConfig configWith:^(BuzzBenefitConfigBuilder * _Nonnull builder) {
builder.appId = @"YOUR_APP_ID";
}];
[[BuzzBenefit sharedInstance] initializeWith:config];
Reference — Previous code (BuzzAdBenefit SDK v5)
import BuzzvilSDK
let config = BuzzBenefitConfig.Builder(appID: "YOUR_APP_ID")
.build()
BuzzBenefit.shared.initialize(with: config)
@import BuzzvilSDK;
BuzzBenefitConfig *config = [BuzzBenefitConfig configWithBlock:^(BuzzBenefitConfigBuilder * _Nonnull builder) {
builder.appID = @"YOUR_APP_ID";
}];
[[BuzzBenefit sharedInstance] initializeWithConfig:config];
Configure dark mode
Dark mode is now configured through server settings rather than code. Remove the previous dark-mode-related code.
| Dark mode option | Description |
|---|---|
BuzzBenefitUserInterfaceStyleLight | Uses light mode regardless of the system's dark mode setting. |
BuzzBenefitUserInterfaceStyleDark | Uses dark mode regardless of the system's dark mode setting. |
BuzzBenefitUserInterfaceStyleSystem | The SDK's default dark mode setting (기본 값). Uses the system's dark mode setting. |
Remove the functions previously used to configure dark mode.
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
}
}
@import BuzzvilSDK;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ...생략...
[[BuzzBenefit sharedInstance] setUserInterfaceStyle:BuzzBenefitUserInterfaceStyleSystem]; // 삭제 처리
return YES;
}
@end
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.
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
}
}
@import BuzzvilSDK;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
BuzzBenefitConfig *config = [BuzzBenefitConfig configWith:^(BuzzBenefitConfigBuilder * _Nonnull builder) {
builder.appId = @"YOUR_APP_ID";
}];
[BuzzBenefit sharedInstance] initializeWithConfig:config];
return YES;
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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
}
}
@import BuzzvilSDK;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
BZVFeedConfig *feedConfig = [BZVFeedConfig configWithBlock:^(BZVFeedConfigBuilder * _Nonnull builder) {
builder.unitID = @"YOUR_FEED_UNIT_ID";
}];
BuzzBenefitConfig *config = [BuzzBenefitConfig configWithBlock:^(BuzzBenefitConfigBuilder * _Nonnull builder) {
builder.appID = @"YOUR_APP_ID";
builder.defaultFeedConfig = feedConfig;
}];
[BuzzBenefit sharedInstance] initializeWithConfig:config];
return YES;
}
@end
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.
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
benefitHub.show(on: yourViewController)
UIViewController *yourViewController = [[UIViewController alloc] init];
BuzzBenefitHub *benefitHub = [[BuzzBenefitHub alloc] init];
[benefitHub showOn:yourViewController];
Reference — Previous code (BuzzAdBenefit SDK v5)
/** 참고 - 변경 전 코드(BuzzAdBenefit v5) **/
let yourViewController = UIViewController()
let buzzAdFeed = BZVBuzzAdFeed { _ in }
buzzAdFeed.show(on: yourViewController)
/** 참고 - 변경 전 코드(BuzzAdBenefit v5) **/
UIViewController *yourViewController = [[UIViewController alloc] init];
BZVBuzzAdFeed *buzzAdFeed = [BZVBuzzAdFeed feedWithBlock:^(BZVBuzzAdFeedBuilder * _Nonnull builder) {}];
[buzzAdFeed showOn: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.
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
let benefitHubConfig = BuzzBenefitHubConfig.Builder()
.setQueryParams(BuzzBenefitHubPage.luckyBox.toRedirectQueryParams())
.build()
benefitHub.setConfig(benefitHubConfig)
benefitHub.show(on: yourViewController)
UIViewController *yourViewController = [[UIViewController alloc] init];
BuzzBenefitHubConfig * benefithubConfig = [BuzzBenefitHubConfig configWith:^(BuzzBenefitHubConfigBuilder * _Nonnull builder) {
builder.queryParams = [BuzzBenefitHubPage.luckyBox toRedirectQueryParams];
}];
[self.benefitHub setConfig:benefithubConfig];
[benefitHub showOn:yourViewController];
Reference — Previous code (BuzzAdBenefit SDK v5)
/** 참고 - 변경 전 코드(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
})
/** 참고 - 변경 전 코드(BuzzAdBenefit v5) **/
UIViewController *yourViewController = [[UIViewController alloc] init];
BZVFeedConfig *feedConfig = [BZVFeedConfig configWithBlock:^(BZVFeedConfigBuilder * _Nonnull builder) {
builder.unitID = @"BENEFITHUB_UNIT_ID";
builder.initialNavigationPage = BZVFeedInitialNavigationPageLuckyBox;
}];
BZVBuzzAdFeed *buzzAdFeed = [BZVBuzzAdFeed feedWithBlock:^(BZVBuzzAdFeedBuilder * _Nonnull builder) {
builder.config = feedConfig;
}];
[buzzAdFeed showOn:yourViewController];
Mission Pack
You can now open Mission Pack directly through the BenefitHub object. The code for opening Mission Pack directly has changed.
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
let benefitHubConfig = BuzzBenefitHubConfig.Builder()
.setQueryParams(BuzzBenefitHubPage.missionPack.toRedirectQueryParams())
.build()
benefitHub.setConfig(benefitHubConfig)
benefitHub.show(on: yourViewController)
UIViewController *yourViewController = [[UIViewController alloc] init];
BuzzBenefitHubConfig * benefithubConfig = [BuzzBenefitHubConfig configWith:^(BuzzBenefitHubConfigBuilder * _Nonnull builder) {
builder.queryParams = [BuzzBenefitHubPage.missionPack toRedirectQueryParams];
}];
[self.benefitHub setConfig:benefithubConfig];
[benefitHub showOn:yourViewController];
Reference — Previous code (BuzzAdBenefit SDK v5)
/** 참고 - 변경 전 코드(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
})
/** 참고 - 변경 전 코드(BuzzAdBenefit v5) **/
UIViewController *yourViewController = [[UIViewController alloc] init];
BZVFeedConfig *feedConfig = [BZVFeedConfig configWithBlock:^(BZVFeedConfigBuilder * _Nonnull builder) {
builder.unitID = @"BENEFITHUB_UNIT_ID";
builder.initialNavigationPage = BZVFeedInitialNavigationPageMissionPack;
}];
BZVBuzzAdFeed *buzzAdFeed = [BZVBuzzAdFeed feedWithBlock:^(BZVBuzzAdFeedBuilder * _Nonnull builder) {
builder.config = feedConfig;
}];
[buzzAdFeed showOn:yourViewController];
Reward history
A new page displays reward history, which was previously unavailable. You can also open it directly without going through BenefitHub.
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
let benefitHubConfig = BuzzBenefitHubConfig.Builder()
.setQueryParams(BuzzBenefitHubPage.history.toRedirectQueryParams())
.build()
benefitHub.setConfig(benefitHubConfig)
benefitHub.show(on: yourViewController)
UIViewController *yourViewController = [[UIViewController alloc] init];
BuzzBenefitHubConfig * benefithubConfig = [BuzzBenefitHubConfig configWith:^(BuzzBenefitHubConfigBuilder * _Nonnull builder) {
builder.queryParams = [BuzzBenefitHubPage.history toRedirectQueryParams];
}];
[self.benefitHub setConfig:benefithubConfig];
[benefitHub showOn: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.
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)
}
}
@import BuzzvilSDK;
@interface ContainerViewController ()
@property (nonatomic, strong, readonly) BuzzBenefitHub *benefitHub;
@end
@implementation ContainerViewController
- (void)viewDidLoad {
[super viewDidLoad];
_benefitHub = [[BuzzBenefitHub alloc] init];
[self displayContentViewController:[_benefitHub getViewController]];
}
- (void)displayContentViewController:(UIViewController*)contentViewController {
[self addChildViewController:contentViewController];
contentViewController.view.frame = self.view.bounds;
[self.view addSubview:contentViewController.view];
[contentViewController didMoveToParentViewController:self];
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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)
}
}
@import BuzzvilSDK;
@interface ContainerViewController ()
@property (nonatomic, strong, readonly) BZVBuzzAdFeed *buzzAdFeed;
@end
@implementation ContainerViewController
- (void)viewDidLoad {
[super viewDidLoad];
_buzzAdFeed = [BZVBuzzAdFeed feedWithBlock:^(BZVBuzzAdFeedBuilder * _Nonnull builder) {}];
[self displayContentViewController:[_buzzAdFeed viewController]];
}
- (void)displayContentViewController:(UIViewController*)contentViewController {
[self addChildViewController:contentViewController];
contentViewController.view.frame = self.view.bounds;
[self.view addSubview:contentViewController.view];
[contentViewController didMoveToParentViewController:self];
}
@end
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.
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 설정
// ...
}
}
@import BuzzvilSDK;
@interface ViewController ()
@property (nonatomic, strong, readonly) BuzzNativeAdView *nativeAdView;
@property (nonatomic, strong, readonly) BuzzMediaView *mediaView;
@property (nonatomic, strong, readonly) UIImageView *iconImageView;
@property (nonatomic, strong, readonly) UILabel *titleLabel;
@property (nonatomic, strong, readonly) UILabel *descriptionLabel;
@property (nonatomic, strong, readonly) BuzzDefaultCtaView *ctaView;
@property (nonatomic, strong, readonly) BuzzNativeViewBinder *viewBinder;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_nativeAdView = [[BuzzNativeAdView alloc] initWithFrame:CGRectZero];
[self.view addSubview:_nativeAdView];
_mediaView = [[BuzzMediaView alloc] initWithFrame:CGRectZero];
[_nativeAdView addSubview:_mediaView];
_iconImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
[_nativeAdView addSubview:_iconImageView];
_titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[_nativeAdView addSubview:_titleLabel];
_descriptionLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[_nativeAdView addSubview:_descriptionLabel];
_ctaView = [[BuzzDefaultCtaView alloc] initWithFrame:CGRectZero];
[_nativeAdView addSubview:_ctaView];
_viewBinder = [BuzzNativeViewBinder viewBinderWithk:^(BuzzNativeViewBinderBuilder * _Nonnull builder) {
builder.nativeAdView = self.nativeAdView;
builder.mediaView = self.mediaView;
builder.iconImageView = self.iconImageView;
builder.titleLabel = self.titleLabel;
builder.descriptionLabel = self.descriptionLabel;
builder.ctaView = self.ctaView;
}];
// AutoLayout Constraints 설정
// ...
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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 설정
// ...
}
}
@import BuzzvilSDK;
@interface ViewController ()
@property (nonatomic, strong, readonly) BZVNativeAd2View *nativeAd2View;
@property (nonatomic, strong, readonly) BZVMediaView *mediaView;
@property (nonatomic, strong, readonly) UIImageView *iconImageView;
@property (nonatomic, strong, readonly) UILabel *titleLabel;
@property (nonatomic, strong, readonly) UILabel *descriptionLabel;
@property (nonatomic, strong, readonly) BZVDefaultCtaView *ctaView;
@property (nonatomic, strong, readonly) BZVNativeAd2ViewBinder *viewBinder;
@property (nonatomic, strong, readonly) BZVNativeToFeedView *nativeToFeedView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_nativeAd2View = [[BZVNativeAd2View alloc] initWithFrame:CGRectZero];
[self.view addSubview:_nativeAd2View];
_mediaView = [[BZVMediaView alloc] initWithFrame:CGRectZero];
[_nativeAd2View addSubview:_mediaView];
_iconImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
[_nativeAd2View addSubview:_iconImageView];
_titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[_nativeAd2View addSubview:_titleLabel];
_descriptionLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[_nativeAd2View addSubview:_descriptionLabel];
_ctaView = [[BZVDefaultCtaView alloc] initWithFrame:CGRectZero];
[_nativeAd2View addSubview:_ctaView];
_viewBinder = [BZVNativeAd2ViewBinder viewBinderWithBlock:^(BZVNativeAd2ViewBinderBuilder * _Nonnull builder) {
builder.unitId = @"YOUR_NATIVE_UNIT_ID";
builder.nativeAd2View = self.nativeAd2View;
builder.mediaView = self.mediaView;
builder.iconImageView = self.iconImageView;
builder.titleLabel = self.titleLabel;
builder.descriptionLabel = self.descriptionLabel;
builder.ctaView = self.ctaView;
}];
_nativeToFeedView = [[BZVNativeToFeedView alloc] initWithFrame:CGRectZero];
[self.view addSubview:_nativeToFeedView];
[_nativeToFeedView setWithUnitId:@"YOUR_NATIVE_UNIT_ID"];
// AutoLayout Constraints 설정
// ...
}
@end
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.
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)
}
}
@interface ViewController ()
@property (nonatomic, strong, readonly) BuzzNative *native;
@property (nonatomic, strong, readonly) BuzzNativeViewBinder *viewBinder;
@end
@implementation ViewController
- (void)viewDidLoad {
// ...생략...
// Warning: retain cycle 방지를 위해 weak self를 사용해주세요.
__weak typeof(self) weakSelf = self;
[_viewBinder subscribeRefreshEvents:^{
// 광고 갱신 할당을 요청한 상태입니다.
// 이후에는 onSuccess, onFailure 중 하나가 호출됩니다.
// 광고 자동 갱신을 시도할 때마다 반복적으로 호출됩니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
// ...
}
} onSuccess:^(BuzzNativeAd * _Nonnull nativeAd) {
// 광고 갱신 할당에 성공하면 호출됩니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
// ...
}
} onError:^(NSError * _Nonnull error) {
// 더 이상 갱신할 수 있는 광고가 없을 때 호출됩니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
// ...
}
}];
// 광고 할당을 수행합니다.
[_native loadOnSuccess:^(BuzzNativeAd * _Nonnull nativeAd) {
// 초기 광고 할당에 성공하면 호출됩니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
// ...
}
} onFailure:^(NSError * _Nonnull error) {
// 초기 광고 할당에 실패하면 호출됩니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
// ...
}
}];
// 할당된 광고 표시를 자동으로 수행합니다.
[_viewBinder bindWithNative:_native];
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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()
}
}
@interface ViewController ()
// ...생략...
@property (nonatomic, strong, readonly) UIActivityIndicatorView *activityIndicatorView;
@end
@implementation ViewController
- (void)viewDidLoad {
// ...생략...
// Warning: retain cycle 방지를 위해 weak self를 사용해주세요.
__weak typeof(self) weakSelf = self;
[_viewBinder subscribeEventsOnRequest:^{
// 광고 할당을 요청하면 호출됩니다.
// 이후에는 onNext, onCompleted, onError 중 하나가 호출됩니다.
// 광고 자동 갱신을 시도할 때마다 반복적으로 호출됩니다.
// 로딩 화면 등을 구현할 수 있습니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView startAnimating];
}
} onNext:^(BZVNativeAd2 * _Nonnull nativeAd2) {
// 광고 할당에 성공하면 호출됩니다.
// 이후에 광고 갱신 시 onRequest가 다시 호출됩니다.
// 광고 자동 갱신을 성공할 때마다 반복적으로 호출됩니다.
// 로딩 화면 등을 구현한 경우, 여기에서 로딩을 종료합니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
}
} onError:^(NSError * _Nonnull error) {
// 최초 광고 할당에 실패하면 호출됩니다.
// 로딩 화면 등을 구현한 경우, 여기에서 로딩을 종료합니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
}
// NativeAd2View를 숨기거나, Error UI로 대체할 수 있습니다.
NSLog(@"Failed to load ad by %@.", error.localizedDescription);
} onCompleted:^{
// 더 이상 갱신할 수 있는 광고가 없을 때 호출됩니다.
// 로딩 화면 등을 구현한 경우, 여기에서 로딩을 종료합니다.
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
}
}];
// 광고 할당 및 표시를 자동으로 수행합니다.
[_viewBinder bind];
}
@end
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)
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 = "더 많은 참여 기회 보기"
}
}
__weak typeof(self) weakSelf = self;
[BuzzAdBenefit getAvailableFeedBaseRewardFor:@"YOUR_FEED_UNIT_ID" onComplete:^(NSInteger reward) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
if (reward > 0) {
strongSelf.nativeToFeedLabel.text = [NSString stringWithFormat:@"%d 포인트 받고 더 많은 참여 기회 보기", reward];
} else {
strongSelf.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)
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) {
// 비디오 광고의 비디오가 종료되면 호출됩니다.
}
}
@import BuzzvilSDK;
@interface ViewController () <BZVNativeAdViewVideoDelegate>
@property (nonatomic, strong, readonly) BZVNativeAd2View *nativeAd2View;
// ...생략...
@end
@implementation ViewController
- (void)viewDidLoad {
// ...생략...
_nativeAd2View.videoDelegate = self;
}
#pragma mark - BZVNativeAdViewVideoDelegate
- (void)BZVNativeAdView:(BZVNativeAdView *)nativeAdView willStartPlayingVideoAd:(BZVNativeAd *)nativeAd {
// 비디오 광고의 비디오가 시작하기 직전에 호출됩니다.
}
- (void)BZVNativeAdView:(BZVNativeAdView *)nativeAdView didResumeVideoAd:(BZVNativeAd *)nativeAd {
// 비디오 광고의 비디오가 재생되면 호출됩니다.
}
- (void)BZVNativeAdView:(BZVNativeAdView *)nativeAdView willReplayVideoAd:(BZVNativeAd *)nativeAd {
// 비디오 광고의 비디오가 리플레이되면 호출됩니다.
}
- (void)BZVNativeAdView:(BZVNativeAdView *)nativeAdView didPauseVideoAd:(BZVNativeAd *)nativeAd {
// 비디오 광고의 비디오가 일시정지되면 호출됩니다.
}
- (void)BZVNativeAdView:(BZVNativeAdView *)nativeAdView didFinishPlayingVideoAd:(BZVNativeAd *)nativeAd {
// 비디오 광고의 비디오가 종료되면 호출됩니다.
}
@end
Register an ad event listener
Ad events previously received through BZVNativeAd2ViewBinder are now received through the BuzzNative object. Update your code accordingly.
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
// 광고 참여가 완료되었을 때 호출됩니다.
})
// ...생략...
}
}
@implementation ViewController
- (void)viewDidLoad {
// ...생략...
// Native 광고 이벤트 처리를 위한 closure를 등록하고 각 이벤트에 따라 필요한 기능을 구현합니다.
// Warning: retain cycle 방지를 위해 closure 내에서 반드시 weak self를 사용해주세요.
__weak typeof(self) weakSelf = self;
[_native subscribeAdEventsOnImpressed:^(BuzzNativeAd * _Nonnull nativeAd) {
__strong typeof(self) strongSelf = weakSelf;
// Native 광고가 유저에게 노출되었을 때 호출됩니다.
} onClicked:^(BuzzNativeAd * _Nonnull nativeAd) {
__strong typeof(self) strongSelf = weakSelf;
// 유저가 Native 광고를 클릭했을 때 호출됩니다.
} onRewardRequested:^(BuzzNativeAd * _Nonnull nativeAd) {
__strong typeof(self) strongSelf = weakSelf;
// 리워드 적립 요청시에 호출됩니다.
} onRewarded:^(BuzzNativeAd * _Nonnull nativeAd, BuzzRewardResult rewardResult) {
__strong typeof(self) strongSelf = weakSelf;
// 리워드 적립 결과를 수신했을 때 호출됩니다.
} onParticipated:^(BuzzNativeAd * _Nonnull nativeAd) {
__strong typeof(self) strongSelf = weakSelf;
// 광고 참여가 완료되었을 때 호출됩니다.
}];
// ...생략...
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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()
}
}
@implementation ViewController
- (void)viewDidLoad {
// ...생략...
// Native 광고 이벤트 처리를 위한 closure를 등록하고 각 이벤트에 따라 필요한 기능을 구현합니다.
// 로그 기록, 단순 알림 외에 다른 동작을 추가하는 것을 권장하지 않습니다. 자동 갱신 등 네이티브 2.0의 기능과 직접 구현한 동작이 충돌할 수 있습니다.
// Warning: 반드시 bind 함수를 호출하기 전에 호출해야 해야합니다.
// Warning: retain cycle 방지를 위해 closure 내에서 반드시 weak self를 사용해주세요.
__weak typeof(self) weakSelf = self;
[_viewBinder subscribeAdEventsOnImpressed:^(BZVNativeAd2 * _Nonnull nativeAd2) {
__strong typeof(self) strongSelf = weakSelf;
// Native 광고가 유저에게 노출되었을 때 호출됩니다.
} onClicked:^(BZVNativeAd2 * _Nonnull nativeAd2) {
__strong typeof(self) strongSelf = weakSelf;
// 유저가 Native 광고를 클릭했을 때 호출됩니다.
} onRewardRequested:^(BZVNativeAd2 * _Nonnull nativeAd2) {
__strong typeof(self) strongSelf = weakSelf;
// 리워드 적립 요청시에 호출됩니다.
} onRewarded:^(BZVNativeAd2 * _Nonnull nativeAd2, BZVRewardResult rewardResult) {
__strong typeof(self) strongSelf = weakSelf;
// 리워드 적립 결과를 수신했을 때 호출됩니다.
} onParticipated:^(BZVNativeAd2 * _Nonnull nativeAd2) {
__strong typeof(self) strongSelf = weakSelf;
// 광고 참여가 완료되었을 때 호출됩니다.
}];
[_viewBinder bind];
}
@end
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-IS | TO-BE |
|---|---|
BZVNativeAd2Pool | BuzzNativeGroup |
BZVNativeAd2Pool.loadAds() | BuzzNativeGroup.load() |
completionHandler | onSuccess |
errorHandler | onFailure |
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 오류 코드에 대한 자세한 내용은 오류 코드가 나타납니다 토픽을 참고하세요.
}
)
}
}
@import BuzzvilSDK;
static NSString * const kUnitId = @"YOUR_UNIT_ID";
@interface CarouselViewController ()
// 최대 10개의 광고를 요청할 수 있습니다.
@property (nonatomic, assign, readonly) NSInteger adRequestCount;
// 실제 할당받은 광고의 개수입니다.
// 이 값은 collectionView datasource의 collectionView(_:numberOfItemsInSection:) 함수의 return 값으로 사용합니다.
@property (nonatomic, assign, readwrite) NSInteger loadedAdCount;
// 광고 중복 할당을 막기 위해 하나의 캐러셀에 하나의 BuzzNativeGroup 인스턴스를 생성하여 사용합니다.
@property (nonatomic, strong, readonly) BuzzNativeGroup *nativeGroup;
@end
@implementation CarouselViewController
- (void)viewDidLoad {
[super viewDidLoad];
_adRequestCount = 5;
_loadedAdCount = 0;
_nativeGroup = [[BuzzNativeGroup alloc] initWithUnitId:kUnitId];
[self setupCarousel];
}
- (void)setupCarousel {
__weak typeof(self) weakSelf = self;
// BuzzNativeGroup에 광고 할당을 요청합니다.
[self.nativeGroup loadWithCount:self.adRequestCount onSuccess:^(NSInteger count) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
// 실제로 할당받은 광고의 개수(count)를 업데이트합니다.
strongSelf.loadedAdCount = count;
}
} onFailure:^(NSError * _Nonnull error) {
// 광고 할당 실패 시 발생하는 NSError 오류 코드에 대한 자세한 내용은 오류 코드가 나타납니다 토픽을 참고하세요.
}];
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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 오류 코드에 대한 자세한 내용은 오류 코드가 나타납니다 토픽을 참고하세요.
}
}
}
@import BuzzvilSDK;
static NSString * const kUnitId = @"YOUR_UNIT_ID";
@interface CarouselViewController ()
// 최대 10개의 광고를 요청할 수 있습니다.
@property (nonatomic, assign, readonly) NSInteger adRequestCount;
// 실제 할당받은 광고의 개수입니다.
// 이 값은 collectionView datasource의 collectionView(_:numberOfItemsInSection:) 함수의 return 값으로 사용합니다.
@property (nonatomic, assign, readwrite) NSInteger loadedAdCount;
// 광고 중복 할당을 막기 위해 하나의 캐러셀에 하나의 NativeAd2Pool 인스턴스를 생성하여 사용합니다.
@property (nonatomic, strong, readonly) BZVNativeAd2Pool *pool;
@end
@implementation CarouselViewController
- (void)viewDidLoad {
[super viewDidLoad];
_adRequestCount = 5;
_loadedAdCount = 0;
_pool = [[BZVNativeAd2Pool alloc] initWithUnitId:kUnitId];
[self setupCarousel];
}
- (void)setupCarousel {
__weak typeof(self) weakSelf = self;
// BZVNativeAd2Pool에 광고 할당을 요청합니다.
[self.pool loadAdsWithCount:self.adRequestCount completionHandler:^(NSInteger adCount) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
// 실제로 할당받은 광고의 개수(adCount)를 업데이트합니다.
strongSelf.loadedAdCount = adCount;
}
} errorHandler:^(NSError * _Nonnull error) {
// 광고 할당 실패 시 발생하는 NSError 오류 코드에 대한 자세한 내용은 오류 코드가 나타납니다 토픽을 참고하세요.
}];
}
@end
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.
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)
}
}
@interface CarouselCell : UICollectionViewCell
- (void)bind:(BuzzNativeAd *)native;
@end
@interface CarouselCell ()
// ...
@property (nonatomic, strong, readonly) BuzzNativeViewBinder *viewBinder;
@end
@implementation CarouselCell
// ...
- (void)prepareForReuse {
[super prepareForReuse];
// prepareForReuse 내에서 unbind를 반드시 호출하여 cell을 재사용할 때 문제가 발생하지 않게 합니다.
[_viewBinder unbind];
}
// collectionView의 collectionView(_:cellForItemAt:) 시점에 호출합니다.
- (void)bind {
// bind()를 호출하면 할당된 광고 표시 및 갱신이 자동으로 수행됩니다.
[_viewBinder bindWithNative:native];
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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()
}
}
@interface CarouselCell : UICollectionViewCell
- (void)setPool:(BZVNativeAd2Pool *)pool forAdKey:(NSInteger)adKey;
- (void)bind;
@end
@interface CarouselCell ()
// ...
@property (nonatomic, strong, readonly) BZVNativeAd2ViewBinder *viewBinder;
@end
@implementation CarouselCell
// ...
- (void)prepareForReuse {
[super prepareForReuse];
// prepareForReuse 내에서 unbind를 반드시 호출하여 cell을 재사용할 때 문제가 발생하지 않게 합니다.
[_viewBinder unbind];
}
// collectionView의 collectionView(_:cellForItemAt:) 시점에 호출합니다.
- (void)setPool:(BZVNativeAd2Pool *)pool forAdKey:(NSInteger)adKey {
// 해당 index(adKey)에 해당하는 NativeAd2ViewBinder가 NativeAd2Pool을 사용하도록 합니다.
[_viewBinder setPool:pool at:adKey];
}
// collectionView의 collectionView(_:cellForItemAt:) 시점에 호출합니다.
- (void)bind {
// NativeAd2ViewBinder의 bind()를 호출하면 광고 할당 및 갱신이 자동으로 수행됩니다.
[_viewBinder bind];
}
@end
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.
let yourViewController = UIViewController()
let benefitHub = BuzzBenefitHub()
benefitHub.show(on: yourViewController)
UIViewController *yourViewController = [[UIViewController alloc] init];
BuzzBenefitHub *benefitHub = [[BuzzBenefitHub alloc] init];
[benefitHub showOn:yourViewController];
Reference — Previous code (BuzzAdBenefit SDK v5)
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),
])
}
}
@import UIKit;
@import BuzzvilSDK;
@interface CarouselFeedEntryView: BZVFeedEntryView
@end
@interface CarouselFeedEntryView ()
@property (nonatomic, strong, readonly) UIButton *button;
@end
@implementation CustomFeedEntryView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupView];
[self setupLayout];
}
return self;
}
- (void)setupView {
_button = [[UIButton alloc] initWithFrame:CGRectZero];
[_button setTitle:@"포인트 더 받으러 가기" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal];
[self addSubview:_button];
self.clickableViews = @[self.button];
}
- (void)setupLayout {
_button.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_button.topAnchor constraintEqualToAnchor:self.topAnchor],
[_button.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[_button.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
[_button.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
]];
}
@end
Implement optional carousel features
Implement a loading screen
The previously separate function has moved into bind(with native: BuzzNative) in the UICollectionViewCell.
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
}
}
@interface CarouselCell ()
// ...
@property (nonatomic, strong, readonly) UIActivityIndicatorView *activityIndicatorView;
@end
@implementation CarouselCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupView];
[self setupLayout];
}
return self;
}
- (void)setupView {
// ...
_activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
_activityIndicatorView.hidesWhenStopped = YES;
[self.contentView addSubview:_activityIndicatorView];
}
- (void)setupLayout {
// ...
_activityIndicatorView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_activityIndicatorView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
[_activityIndicatorView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
]];
}
- (void)bindWithNative:(BuzzNative *)native {
__weak typeof(self) weakSelf = self;
[_native subscribeRefreshEventsOnRequest:^{
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView startAnimating];
strongSelf.nativeAdView.alpha = 0.5;
}
} onSuccess:^{
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
strongSelf.nativeAdView.alpha = 1;
}
} onFailure:^(NSError * _Nonnull error) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
strongSelf.nativeAdView.alpha = 1;
}
}];
}
@end
@implementation CarouselViewController
// ...
#pragma mark - UICollectionViewDataSource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// ...
[cell bindWithNative:native];
return cell;
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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
}
}
@interface CarouselCell : UICollectionViewCell
// ...
- (void)setupLoading
@end
@interface CarouselCell ()
// ...
@property (nonatomic, strong, readonly) UIActivityIndicatorView *activityIndicatorView;
@end
@implementation CarouselCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupView];
[self setupLayout];
}
return self;
}
- (void)setupView {
// ...
_activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
_activityIndicatorView.hidesWhenStopped = YES;
[self.contentView addSubview:_activityIndicatorView];
}
- (void)setupLayout {
// ...
_activityIndicatorView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_activityIndicatorView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
[_activityIndicatorView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
]];
}
- (void)setupLoading {
__weak typeof(self) weakSelf = self;
[_viewBinder subscribeEventsOnRequest:^{
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView startAnimating];
strongSelf.nativeAd2View.alpha = 0.5;
}
} onNext:^(BZVNativeAd2 * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
strongSelf.nativeAd2View.alpha = 1;
}
} onError:^(NSError * _Nonnull error) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
strongSelf.nativeAd2View.alpha = 1;
NSLog(@"error: %@", error);
}
} onCompleted:^{
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf.activityIndicatorView stopAnimating];
strongSelf.nativeAd2View.alpha = 1;
NSLog(@"completed");
}
}];
}
@end
@implementation CarouselViewController
// ...
#pragma mark - UICollectionViewDataSource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// ...
[cell setupLoading];
[cell setPool:_pool forIndex:indexPath.item];
[cell bind];
return cell;
}
@end
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.
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
}
}
@implementation CarouselCell
// ...
- (void)bindWithNative:(BuzzNative *)native {
__weak typeof(self) weakSelf = self;
[native subscribeAdEventsOnImpressed:^(BuzzNativeAd * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"impressed: %@", ad.title);
}
} onClicked:^(BuzzNativeAd * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"clicked: %@", ad.title);
}
} onRewardRequested:^(BuzzNativeAd * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"requested reward: %@", ad.title);
}
} onRewarded:^(BuzzNativeAd * _Nonnull ad, BuzzRewardResult result) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"received reward result: %@", ad.title);
}
} onParticipated:^(BuzzNativeAd * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"participated: %@", ad.title);
}
}];
}
@end
@implementation CarouselViewController
// ...
#pragma mark - UICollectionViewDataSource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// ...
[cell bindWithNative:native];
return cell;
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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
}
}
@interface CarouselCell : UICollectionViewCell
// ...
- (void)setupEventListeners;
@end
@implementation CarouselCell
// ...
- (void)setupEventListeners {
__weak typeof(self) weakSelf = self;
[_viewBinder subscribeAdEventsOnImpressed:^(BZVNativeAd2 * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"impressed: %@", ad.title);
}
} onClicked:^(BZVNativeAd2 * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"clicked: %@", ad.title);
}
} onRewardRequested:^(BZVNativeAd2 * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"requested reward: %@", ad.title);
}
} onRewarded:^(BZVNativeAd2 * _Nonnull ad, BZVRewardResult result) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"received reward result: %@", ad.title);
}
} onParticipated:^(BZVNativeAd2 * _Nonnull ad) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"participated: %@", ad.title);
}
}];
}
@end
@implementation CarouselViewController
// ...
#pragma mark - UICollectionViewDataSource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// ...
[cell setupEventListeners];
[cell setPool:_pool forIndex:indexPath.item];
[cell bind];
return cell;
}
@end
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.
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 지면이 종료되면 호출됩니다.
// 필요에 따라 추가 기능을 구현하세요.
}
}
@import BuzzvilSDK;
@interface ViewController () <BuzzInterstitialDelegate>
@property (nonatomic, strong, readonly) BuzzInterstitial *buzzAdInterstitial;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_buzzAdInterstitial = [[BuzzInterstitial alloc] initWithUnitId:@"YOUR_INTERSTITIAL_UNIT_ID" type:BuzzInterstitialTypeDialog];
_buzzAdInterstitial.delegate = self;
[_buzzAdInterstitial load];
}
#pragma mark - BuzzInterstitialDelegate
- (void)BuzzInterstitialDidLoadAd:(BuzzInterstitial *)interstitial {
// 할당된 광고가 있으면 호출됩니다.
// Interstitial 광고를 화면에 표시합니다.
[interstitial presentOnViewController:self];
}
- (void)BuzzInterstitialDidFailToLoadAd:(BuzzInterstitial *)interstitial withError:(NSError *)error {
// 할당된 광고가 없으면 호출됩니다.
}
- (void)BuzzInterstitialDidDismiss:(UIViewController *)viewController {
// Interstitial 지면이 종료되면 호출됩니다.
// 필요에 따라 추가 기능을 구현하세요.
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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 지면이 종료되면 호출됩니다.
// 필요에 따라 추가 기능을 구현하세요.
}
}
@import BuzzvilSDK;
@interface ViewController () <BZVBuzzAdInterstitialDelegate>
@property (nonatomic, strong, readonly) BZVBuzzAdInterstitial *buzzAdInterstitial;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_buzzAdInterstitial = [BZVBuzzAdInterstitial interstitialWithBlock:^(BZVBuzzAdInterstitialBuilder * _Nonnull builder) {
builder.unitId = @"YOUR_INTERSTITIAL_UNIT_ID";
builder.type = BZVBuzzAdInterstitialTypeDialog;
}];
_buzzAdInterstitial.delegate = self;
[_buzzAdInterstitial load];
}
#pragma mark - BZVBuzzAdInterstitialDelegate
- (void)BZVBuzzAdInterstitialDidLoadAd:(BZVBuzzAdInterstitial *)interstitial {
// 할당된 광고가 있으면 호출됩니다.
// Interstitial 광고를 화면에 표시합니다.
[interstitial presentOnViewController:self];
}
- (void)BZVBuzzAdInterstitialDidFailToLoadAd:(BZVBuzzAdInterstitial *)interstitial withError:(NSError *)error {
// 할당된 광고가 없으면 호출됩니다.
}
- (void)BZVBuzzAdInterstitialDidDismiss:(UIViewController *)viewController {
// Interstitial 지면이 종료되면 호출됩니다.
// 필요에 따라 추가 기능을 구현하세요.
}
@end
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.
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) // 삭제 처리
}
BZVFeedConfig *feedConfig = [BZVFeedConfig configWithBlock:^(BZVFeedConfigBuilder * _Nonnull builder) {
builder.unitID = @"YOUR_FEED_UNIT_ID";
}];
BZVBuzzAdInterstitial *buzzAdInterstitial = [BZVBuzzAdInterstitial interstitialWithBlock:^(BZVBuzzAdInterstitialBuilder * _Nonnull builder) {
builder.unitId = @"YOUR_INTERSTITIAL_UNIT_ID";
builder.type = BZVBuzzAdInterstitialTypeDialog;
builder.buzzAdBenefitRouter = [BuzzBenefitRouterFactory createFeedRouter:feedConfig];
}];
BuzzBanner
The class names have changed. Review the changes below and update them accordingly.
| AS-IS | TO-BE |
|---|---|
| BuzzAdBenefitBannerView | BuzzBannerSize |
| BuzzAdBenefitBannerSize | BuzzBannerView |
| BuzzAdBenefitBannerViewDelegate | BuzzBannerViewDelegate |
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가 제거되었을 떄 호출 됩니다.
}
}
@import BuzzvilSDK;
@interface ViewController () <BuzzBannerViewDelegate>
@property (nonatomic, strong, readonly) BuzzBannerView *bannerView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupView];
}
- (void)setupView {
BuzzBannerConfig * config = [BuzzBannerConfig configWith:^(BuzzBannerConfigBuilder * _Nonnull builder) {
builder.placementId = @"YOUR_PLCEMENT_ID";
builder.size = BuzzBannerSizeW320h50;
}];
_bannerView = [[BuzzBannerView alloc] initWithFrame:CGRectZero];
[_bannerView setConfigWithRootViewController:self config:config];
[self.view addSubview:_bannerView];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[_bannerView requestAd];
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[_bannerView removeAd];
}
#pragma mark - BuzzBannerViewDelegate
- (void)bannerView:(BuzzBannerView * _Nonnull)bannerView didClickApid:(NSString * _Nonnull)didClickApid {
// Banner에 광고가 할당 되었을 때 호출 됩니다.
}
- (void)bannerView:(BuzzBannerView * _Nonnull)bannerView didFailApid:(NSString * _Nonnull)didFailApid error:(NSError * _Nonnull)error {
// Banner에 광고 할당이 실패했을 때 호출 됩니다.
}
- (void)bannerView:(BuzzBannerView * _Nonnull)bannerView didLoadApid:(NSString * _Nonnull)didLoadApid {
// Banner가 클릭되었을 때 호출 됩니다.
}
- (void)bannerView:(BuzzBannerView * _Nonnull)bannerView didRemoveApid:(NSString * _Nonnull)didRemoveApid {
// Banner가 제거되었을 떄 호출 됩니다.
}
@end
Reference — Previous code (BuzzAdBenefit SDK v5)
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가 제거되었을 떄 호출 됩니다.
}
}
@import BuzzvilSDK;
@interface ViewController () <BuzzAdBenefitBannerViewDelegate>
@property (nonatomic, strong, readonly) BuzzAdBenefitBannerView *bannerView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupView];
}
- (void)setupView {
BuzzAdBenefitBannerConfig * config = [BuzzAdBenefitBannerConfig configWithBlock:^(BuzzAdBenefitBannerConfigBuilder * _Nonnull builder) {
builder.placementID = @"YOUR_PLACEMENT_ID";
builder.size = BuzzAdBenefitBannerSizeW320h50;
}];
_bannerView = [[BuzzAdBenefitBannerView alloc] initWithFrame:CGRectZero];
[_bannerView setConfigWithRootViewController:self config:config];
[self.view addSubview:_bannerView];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[_bannerView requestAd];
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[_bannerView removeAd];
}
#pragma mark - BuzzAdBenefitBannerViewDelegate
- (void)bannerView:(BuzzAdBenefitBannerView * _Nonnull)bannerView didClickApid:(NSString * _Nonnull)didClickApid {
// Banner에 광고가 할당 되었을 때 호출 됩니다.
}
- (void)bannerView:(BuzzAdBenefitBannerView * _Nonnull)bannerView didFailApid:(NSString * _Nonnull)didFailApid error:(NSError * _Nonnull)error {
// Banner에 광고 할당이 실패했을 때 호출 됩니다.
}
- (void)bannerView:(BuzzAdBenefitBannerView * _Nonnull)bannerView didLoadApid:(NSString * _Nonnull)didLoadApid {
// Banner가 클릭되었을 때 호출 됩니다.
}
- (void)bannerView:(BuzzAdBenefitBannerView * _Nonnull)bannerView didRemoveApid:(NSString * _Nonnull)didRemoveApid {
// Banner가 제거되었을 떄 호출 됩니다.
}
@end
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
// 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)
}
@objc
public protocol BuzzCtaViewProtocol: AnyObject {
@objc
func renderParticipatingViewState(ctaText: String)
@objc
func renderParticipatedViewState(ctaText: String)
@objc
func renderRewardAvailableViewState(ctaText: String, reward: Int)
@objc
func renderRewardNotAvailableViewState(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)
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)
}
}
@interface CustomBrowserViewController: UIViewController
@end
@interface CustomBrowserViewController ()
@property (nonatomic, strong, readonly) UIViewController *browserViewController;
@end
@implementation CustomBrowserViewController
- (void)viewDidLoad {
[super viewDidLoad];
_browserViewController = [BuzzAdBrowser.sharedInstance browserViewController];
[self displayContentViewController:_browserViewController];
}
- (void)displayContentViewController:(UIViewController *)contentViewController {
[self addChildViewController:contentViewController];
contentViewController.view.frame = self.view.bounds;
[self.view addSubview:contentViewController.view];
[contentViewController didMoveToParentViewController:self];
}
@end
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)
}
}
@import BuzzvilSDK;
@interface CustomLauncher : NSObject <BZVLauncher>
// 런처와 관련된 이벤트를 수신할 수 있습니다.
@property (nonatomic, weak, readwrite, nullable) id<BZVLauncherDelegate> delegate;
@end
@implementation CustomLauncher
- (void)openWithLaunchInfo:(BZVLaunchInfo *)launchInfo {
// launchInfo의 인자를 확인하여 광고 또는 콘텐츠인지 미리 판단할 수 있습니다.
if (launchInfo.ad != nil) {
if (launchInfo.ad.isDeepLink) {
// 딥링크 광고일 경우 필요한 작업을 할 수 있습니다.
}
} else if (launchInfo.article != nil){
NSString *sourceURL = launchInfo.article.sourceURL;
}
// Custom Browser 실행
CustomBrowserViewController *customBrowserViewController = [[CustomBrowserViewController alloc] init];
[YOUR_ROOT_VIEW_CONTROLLER.presentedViewController presentViewController:customBrowserViewController animated:YES completion:nil];
}
@end
let launcher = CustomLauncher()
BuzzAdBenefit.setLauncher(launcher)
CustomLauncher *launcher = [[CustomLauncher alloc] init];
[BuzzAdBenefit setLauncher:launcher];
Agree to the privacy policy
The functions for checking privacy policy consent and providing consent have changed.
| Status | enum |
|---|---|
| Agreed | BuzzPrivacyConsentStatus.granted |
| Denied | BuzzPrivacyConsentStatus.revoked |
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
// 개인정보 처리방침 동의 요청에 실패했을 경우 호출 됩니다.
})
[BuzzAdBenefit.sharedInstance loadPrivacyConsentStatusOnSuccess:^(enum BuzzPrivacyConsentStatus status) {
// 현재 개인정보 처리 방침 상태를 가져올 수 있습니다
} onFailure:^(NSError * _Nonnull error) {
// 개인정보 처리방침에 대한 상태를 가져오는데 실패 했을 경우 호출 됩니다.
}];
[BuzzAdBenefit.sharedInstance grantPrivacyConsentOnSuccess:^{
// 개인정보 처리방침 동의에 성공했을 경우 호출 됩니다.
} onFailure:^(NSError * _Nonnull error) {
// 개인정보 처리방침 동의 요청에 실패했을 경우 호출 됩니다.
}];
Reference — Previous code (BuzzAdBenefit SDK v5)
let privacyPolicyManager = BuzzAdBenefit.privacyPolicyManager
// 직접 구현한 개인정보 제3자 제공 동의 UI에서 동의를 받았을 경우 아래 코드를 실행하면, 피드 화면에서 개인정보 제3자 제공 동의 UI가 노출되지 않으면서 광고 할당이 정상적으로 진행 됩니다.
// 아래의 코드를 실행하지 않을 경우 피드 진입 시 개인정보 제3자 제공 동의 UI가 노출되기 때문에 필수적으로 실행이 필요합니다.
privacyPolicyManager.grantConsent()
// 아래 코드를 통해서 수집 동의를 철회할 수 있습니다. 이 코드가 실행되면 피드에서 광고 할당이 이루어지지 않습니다.
privacyPolicyManager.revokeConsent()
BZVPrivacyPolicyManager *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)
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)")
})
}
}
@import BuzzvilSDK;
#import "MissionPackViewController.h"
@interface MissionPackViewController()
@property (nonatomic, strong, readonly) BuzzAdBenefitMissionPack * missionPack;
@end
@implementation MissionPackViewController
- (void)viewDidLoad {
[super viewDidLoad];
_missionPack = [[BuzzAdBenefitMissionPack alloc] initWithUnitId:@"YOUR_MISSION_PACK_UNIT_ID"];
}
- (void)checkCanOpenMissionPack {
[_missionPack canOpenOnSuccess:^{
// missionPack 이 열릴 수 있을 때 호출 됩니다.
} onFailure:^(NSError * _Nonnull error) {
// missionPack 이 열릴 수 없을 때 호출 됩니다.
}];
}
- (void)showMissionPack {
[_missionPack showOn:self onFailure:^(NSError * _Nonnull error) {
// missionPack 이 열릴 수 없을 때 호출 됩니다.
}];
}
@end