原生广告
大约 8 分钟
原生广告
概述
原生广告是一种与应用内容和设计自然融合的广告形式,开发者只需按照标准集成步骤即可在应用中无缝展示广告内容。原生广告能够与应用的界面和用户体验协调一致,不会干扰用户的正常使用。用户可以在浏览应用内容时自然地接触到这些广告,从而提高广告的接受度和互动性。开发者可以根据应用的风格和用户的需求定制广告的展示方式,以实现最佳的广告效果和用户体验。
原生广告模版渲染和开发者自渲染,统一使用 YTNativeExpressAdManager 加载
YTNativeExpressAdManager 属性及方法介绍
属性 | 说明 | 是否必填 |
---|---|---|
tolerateTimeout | 超时设置 | 非必填,默认5s |
adSize | 广告尺寸 | 使用原生模版渲染时,必填。宽度必须大于0,高度可传0 使用原生自渲染时,可以传想要的宽高 |
delegate | 设置代理 | 必填 |
方法 | 说明 |
---|---|
- (instancetype)initWithSlotId:(NSString *)slotId; | 构造方法,slotId不能为空 |
- (void) loadAdWithCount: (NSInteger)count; | 加载模版信息流 |
- (void) loadAdDataWithCount: (NSInteger) count; | 加载自渲染信息流数据 |
YTNativeExpressAdManagerDelegate 代理方法介绍
@protocol YTNativeExpressAdManagerDelegate <NSObject>
@optional
/// 加载原生模版渲染广告成功
/// - Parameters:
/// - manager: manager
/// - ads: 原生模版广告数组
- (void) yt_nativeExpressAdManager: (YTNativeExpressAdManager *) manager loadSuccess: (NSArray <YTNativeExpressAdView *> *) ads;
/// 加载原生自渲染广告成功
/// - Parameters:
/// - manager: manager
/// - data: 原生广告data数组
- (void) yt_nativeExpressAdManager: (YTNativeExpressAdManager *) manager loadDataSuccess: (NSArray <YTNativeAdData *> *) data;
/// 加载原生模版渲染广告或者原生自渲染广告失败
/// - Parameters:
/// - manager: manager
/// - error: 错误信息
- (void) yt_nativeExpressAdManager: (YTNativeExpressAdManager *) manager didFailWithError: (NSError *) error;
@end
模板渲染
优推SDK提供多种的广告模板样式,上下图文、左右图文、三小图等
模板渲染场景常见于应用的内容信息流中与应用内容穿插展示,如资讯列表页每隔几条资讯穿插一条广告
YTNativeExpressAdView 属性及方法介绍
属性 | 说明 | 是否必填 |
---|---|---|
delegate | 代理 | 必填 |
viewController | 所在的viewController,用于点击事件的跳转等,弱引用 | 必填 |
videoMuted | 广告中的视频是否静音,默认静音 | 可选 |
方法 | 说明 |
---|---|
- (void)render; | 渲染广告视图,在收到yt_nativeExpressAdViewRenderSuccess方法回调后,可以获取广告视图正确的尺寸 |
- (BOOL)isReady; | 对于已经加载成功,但未及时展示的广告,在展示前用此方法判断广告是否还可用 |
YTNativeExpressAdDelegate 方法介绍:
/// 模版信息流view渲染成功
- (void)yt_nativeExpressAdViewRenderSuccess:(YTNativeExpressAdView *)adView;
/// 模版信息流view各种错误信息
- (void)yt_nativeExpressAdView:(YTNativeExpressAdView *)adView didFailWithError:(NSError *_Nullable)error;
/// 模版信息流view即将展示
- (void)yt_nativeExpressAdViewWillShow:(YTNativeExpressAdView *)adView;
/// 模版信息流视频播放状态发生变化
/// - Parameters:
/// - playerControlStatus: 当前只有正在播放和暂停两种状态回调
- (void)yt_nativeExpressAdView:(YTNativeExpressAdView *)adView playerControlStatusDidChange:(YTPlayerControlStatus)playerControlStatus;
/// 模版信息流view被点击
- (void)yt_nativeExpressAdViewDidClick:(YTNativeExpressAdView *)adView;
/// 模版信息流view被关闭
- (void)yt_nativeExpressAdViewDidClose:(YTNativeExpressAdView *)adView;
/// 模版信息流view被曝光
- (void)yt_nativeExpressAdViewDidExposed:(YTNativeExpressAdView *)adView;
接入示例
@interface YTDemoNativeAdsViewController ()<UITableViewDelegate, UITableViewDataSource, YTNativeExpressAdManagerDelegate, YTNativeExpressAdDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *adViews;
@property (nonatomic, strong) YTNativeExpressAdManager *adManager;
@end
@implementation YTDemoNativeAdsViewController
- (void)viewDidLoad {
[super viewDidLoad];
_adViews = [NSMutableArray array];
[_tableView registerClass:UITableViewCell.class forCellReuseIdentifier:@"YTDemoNativeExpressAdCellID"];
}
- (void)loadAds {
NSString *slotId = @"xx";
_adManager = [[YTNativeExpressAdManager alloc] initWithSlotId:slotId];
_adManager.adSize = adSize;
_adManager.delegate = self;
[_adManager loadAdWithCount:count isTemplate:YES];
}
- (void)showAds {
[_tableView reloadData];
}
// MARK: - YTNativeExpressAdManagerDelegate
- (void)yt_nativeExpressAdManager:(YTNativeExpressAdManager *)manager loadSuccess:(NSArray<YTNativeExpressAdView *> *)ads {
[ads enumerateObjectsUsingBlock:^(YTNativeExpressAdView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isReady]) {
obj.delegate = self;
obj.viewController = self;
[self.adViews addObject:obj];
[obj render];
}
}];
_showButton.enabled = YES;
}
- (void)yt_nativeExpressAdManager:(YTNativeExpressAdManager *)manager loadDataSuccess:(NSArray<YTNativeAdData *> *)data {
dispatch_async(dispatch_get_main_queue(), ^{
[self.logTextView insertText: [YTDemoLogTool timePrefixString:@"加载成功\n"]];
[self.adDatas addObjectsFromArray:data];
self.showButton.enabled = YES;
});
}
// MARK: - YTNativeExpressAdDelegate
/// 模版信息流view渲染成功
- (void)yt_nativeExpressAdViewRenderSuccess:(YTNativeExpressAdView *)adView {}
/// 模版信息流view各种错误信息
- (void)yt_nativeExpressAdView:(YTNativeExpressAdView *)adView didFailWithError:(NSError *_Nullable)error {}
/// 模版信息流view即将展示
- (void)yt_nativeExpressAdViewWillShow:(YTNativeExpressAdView *)adView {}
/// 模版信息流视频播放状态发生变化
/// - Parameters:
/// - playerControlStatus: 当前只有正在播放和暂停两种状态回调
- (void)yt_nativeExpressAdView:(YTNativeExpressAdView *)adView playerControlStatusDidChange:(YTPlayerControlStatus)playerControlStatus {}
/// 模版信息流view被点击
- (void)yt_nativeExpressAdViewDidClick:(YTNativeExpressAdView *)adView {}
/// 模版信息流view被关闭
- (void)yt_nativeExpressAdViewDidClose:(YTNativeExpressAdView *)adView {}
/// 模版信息流view被曝光
- (void)yt_nativeExpressAdViewDidExposed:(YTNativeExpressAdView *)adView {}
// MARK: - UITableViewDelegate, UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _adViews.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"YTDemoNativeExpressAdCellID" forIndexPath:indexPath];
[[cell.contentView viewWithTag:1001] removeFromSuperview];
UIView *adView = _adViews[indexPath.row];
adView.tag = 1001;
[cell.contentView addSubview:adView];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UIView *adView = _adViews[indexPath.row];
return adView.bounds.size.height;
}
@end
开发者自渲染
当优推SDK提供的原生模版渲染广告的样式和展示场景无法满足需求时,可以采用原生开发者自渲染广告
使用自渲染的API,您可以自定义广告的布局和展示场景。
使用YTNativeExpressAdManager
调用loadAdDataWithCount
方法,在delegate
的- (void)yt_nativeExpressAdManager:(YTNativeExpressAdManager *)manager loadDataSuccess:(NSArray<YTNativeAdData *> *)data
方法中接收广告数据数组。
YTNativeAdData 属性介绍
自渲染素材类 YTNativeAdData
属性 | 说明 |
---|---|
title | 标题 |
desc | 描述 |
imageUrl | 图片url |
videoUrl | 视频url |
imageUrlList | 图片url数组 |
isVideoAd | 是否是视频类型广告 |
isImageListAd | 是否是多张图 |
duration | 视频时长 |
materialW | 素材宽度:如果为视频类型,则为视频素材宽度;如果为单张大图,则对应imageUrl 图片的宽度;如果为多图类型,则对应imageUrlList 所有图片的宽度。该值可能为0 |
materialH | 素材高度:如果为视频类型,则为视频素材高度;如果为单张大图,则对应imageUrl 图片的高度;如果为多图类型,则对应imageUrlList 所有图片的高度。该值可能为0 |
YTNativeCanvasExpressAdView 属性及方法介绍:
属性 | 说明 | 是否必填 |
---|---|---|
delegate | 代理 | 必填 |
viewController | 所在的viewController,用于点击事件的跳转等,弱引用 | 必填 |
titleLabel | 标题label | 只读 |
descLabel | 描述label | 只读 |
logoImageView | 优推ADN广告logo的ImageView | 只读 |
adSourceLabel | 广告源标识label | 只读 |
closeButton | 关闭按钮 | 只读 |
mainImageView | 当前广告为单张大图时,所需的ImageView | 只读 |
imageViewList | 当前广告为多图时,所需的ImageView数组 | 只读 |
videoPlayerView | 当前广告为视频时,所需的视频播放View | 只读 |
nativeAdData | 广告数据对象 | 只读 |
adAreaClickable | 可选 |
方法 | 说明 |
---|---|
- (void)registerClickableViews:(NSArray<UIView *> *)views; | 注册可点击子视图数组 |
- (void)refreshWithAdData:(YTNativeAdData *)data; | 绑定广告数据对象,渲染广告视图前调用 |
- (void)unregisterAdData; | 解绑广告数据对象 |
YTNativeCanvasExpressAdDelegate 方法介绍
/// 自渲染信息流view渲染成功
- (void)yt_nativeCanvasExpressAdViewRenderSuccess:(YTNativeCanvasExpressAdView *)adView;
/// 自渲染信息流view各种错误信息
- (void)yt_nativeCanvasExpressAdView:(YTNativeCanvasExpressAdView *)adView didFailWithError:(NSError *_Nullable)error;
/// 自渲染信息流view即将展示
- (void)yt_nativeCanvasExpressAdViewWillShow:(YTNativeCanvasExpressAdView *)adView;
/// 自渲染信息流view被点击
- (void)yt_nativeCanvasExpressAdViewDidClick:(YTNativeCanvasExpressAdView *)adView;
/// 自渲染信息流view被关闭
- (void)yt_nativeCanvasExpressAdViewDidClose:(YTNativeCanvasExpressAdView *)adView;
/// 自渲染信息流view被曝光
- (void)yt_nativeCanvasExpressAdViewDidExposed:(YTNativeCanvasExpressAdView *)adView;
YTNativeAdVideoPlayerView 组件方法介绍
方法 | 说明 |
---|---|
- (NSTimeInterval)videoDuration; | 视频广告时长,单位 s |
- (NSTimeInterval)videoPlayTime; | 视频广告已播放时长,单位 s |
- (void)play; | 播放视频 |
- (void)pause; | 暂停视频 |
- (void)stop; | 停止播放,并展示第一帧 |
- (void)setMuted:(BOOL)muted; | 播放静音开关 |
- (void)setPlayButtonImage:(UIImage *)image size:(CGSize)size; | 自定义播放按钮,传入图片和尺寸 |
YTNativeAdVideoPlayerViewDelegate 方法介绍
/// 播放状态发生变化
- (void)yt_nativeAdVideoPlayerView:(YTNativeAdVideoPlayerView *)playerView playStatusDidChange:(YTPlayerControlStatus)status;
/// 视频播放进度发生变化
- (void)yt_nativeAdVideoPlayerView:(YTNativeAdVideoPlayerView *)playerView playTimeDidChange:(NSTimeInterval)time;
YTPlayerControlStatus 视频播放状态枚举
枚举 | 说明 |
---|---|
YTPlayerControlStatusPlaying | 视频开始、正在播放 |
YTPlayerControlStatusPaused | 视频暂停播放 |
YTPlayerControlStatusFinish | 视频播放完毕 |
接入示例
@interface YTDemoNativeCanvasAdsViewController ()<UITableViewDelegate, UITableViewDataSource, YTNativeExpressAdManagerDelegate, YTNativeCanvasExpressAdDelegate, YTNativeAdVideoPlayerViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *adDatas;
@property (nonatomic, strong) YTNativeExpressAdManager *adManager;
@end
@implementation YTDemoNativeCanvasAdsViewController
- (void)viewDidLoad {
[super viewDidLoad];
_adDatas = [NSMutableArray array];
[_tableView registerClass:YTDemoNativeImageAdCell.class forCellReuseIdentifier:@"YTDemoNativeImageAdCellID"];
[_tableView registerClass:YTDemoNativeImageListAdCell.class forCellReuseIdentifier:@"YTDemoNativeImageListAdCellID"];
[_tableView registerClass:YTDemoNativeVideoAdCell.class forCellReuseIdentifier:@"YTDemoNativeVideoAdCellID"];
}
- (void)loadAds {
NSString *slotId = @"xx";
_adManager = [[YTNativeExpressAdManager alloc] initWithSlotId:slotId];
_adManager.adSize = adSize;
_adManager.delegate = self;
[_adManager loadAdDataWithCount:count isTemplate:NO];
}
- (void)showAds {
[_tableView reloadData];
}
// MARK: - YTNativeExpressAdManagerDelegate
- (void)yt_nativeExpressAdManager:(YTNativeExpressAdManager *)manager loadDataSuccess:(NSArray<YTNativeAdData *> *)data {
dispatch_async(dispatch_get_main_queue(), ^{
[self.adDatas addObjectsFromArray:data];
});
}
- (void)yt_nativeExpressAdManager:(YTNativeExpressAdManager *)manager didFailWithError:(NSError *)error {
}
// MARK: - YTNativeCanvasExpressAdDelegate
/// 自渲染信息流view渲染成功
- (void)yt_ativeCanvasExpressAdViewRenderSuccess:(YTNativeCanvasExpressAdView *)adView {}
/// 自渲染信息流view各种错误信息
- (void)yt_nativeCanvasExpressAdView:(YTNativeCanvasExpressAdView *)adView didFailWithError:(NSError *_Nullable)error {}
/// 自渲染信息流view即将展示
- (void)yt_nativeCanvasExpressAdViewWillShow:(YTNativeCanvasExpressAdView *)adView {}
/// 自渲染信息流view被点击
- (void)yt_nativeCanvasExpressAdViewDidClick:(YTNativeCanvasExpressAdView *)adView {}
/// 自渲染信息流view被关闭
- (void)yt_nativeCanvasExpressAdViewDidClose:(YTNativeCanvasExpressAdView *)adView {
[_adDatas removeObject:adView.nativeAdData];
[_tableView reloadData];
}
/// 自渲染信息流view被曝光
- (void)yt_nativeCanvasExpressAdViewDidExposed:(YTNativeCanvasExpressAdView *)adView {}
// MARK: - YTNativeAdVideoPlayerViewDelegate
- (void)yt_nativeAdVideoPlayerView:(YTNativeAdVideoPlayerView *)playerView playStatusDidChange:(YTPlayerControlStatus)status {
NSString *playStatus = @"";
switch (status) {
case YTPlayerControlStatusPlaying:
playStatus = @"播放";
break;
case YTPlayerControlStatusPaused:
playStatus = @"暂停";
break;
default:
playStatus = @"unknown";
break;
}
}
// MARK: - UITableViewDelegate, UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _adDatas.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
YTNativeAdData *data = _adDatas[indexPath.row];
NSString *identifier = @"";
if (data.isVideoAd) {
identifier = @"YTDemoNativeVideoAdCellID";
} else if (data.isImageListAd) {
identifier = @"YTDemoNativeImageListAdCellID";
} else {
identifier = @"YTDemoNativeImageAdCellID";
}
YTDemoNativeCanvasBaseCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
[cell updateCellWithData:data delegate:self viewController:self];
if ([cell isKindOfClass:YTDemoNativeVideoAdCell.class]) {
cell.adView.videoPlayerView.delegate = self;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
YTNativeAdData *data = _adDatas[indexPath.row];
if (data.isVideoAd) {
return [YTDemoNativeVideoAdCell cellHeightWithData:data];
} else if (data.isImageListAd) {
return [YTDemoNativeImageListAdCell cellHeightWithData:data];
} else {
return [YTDemoNativeImageAdCell cellHeightWithData:data];
}
}
@end
/// 自渲染cell YTDemoNativeCanvasBaseCell.h
@interface YTDemoNativeCanvasBaseCell : UITableViewCell
@property (nonatomic, strong) YTNativeCanvasExpressAdView *adView;
- (void)initSubviews;
- (void)updateCellWithData:(YTNativeAdData *)data
delegate:(id<YTNativeCanvasExpressAdDelegate>)delegate
viewController:(UIViewController *)viewController;
+ (CGFloat)cellHeightWithData:(YTNativeAdData *)data;
@end
@interface YTDemoNativeImageAdCell : YTDemoNativeCanvasBaseCell
@end
@interface YTDemoNativeImageListAdCell : YTDemoNativeCanvasBaseCell
@end
@interface YTDemoNativeVideoAdCell : YTDemoNativeCanvasBaseCell
@end
/// YTDemoNativeCanvasBaseCell.m略