跳至主要內容

原生广告

大约 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略
上次编辑于: