广告信息流
广告信息流是由一系列广告组成的单元。信息流可以作为应用的主要内容添加,或者添加到现有内容之后。信息流可能包含数十条广告,而这些广告会按顺序加载(一次加载多个广告)。
本指南介绍如何在 iOS 应用中集成广告信息流。除代码示例与步骤外,还包含格式使用建议及更多资源链接。
外观
前提条件
- 请按照 快速入门 中描述的 SDK 集成步骤进行操作。
- 提前 初始化 您的广告 SDK。
- 确保您运行的是最新的 Yandex Mobile Ads SDK 版本。如果您使用聚合,请同时确保您运行的是最新版本的 统一构建。
实施
集成广告信息流的主要步骤:
- 通过
FeedAdAppearance配置信息流外观。 - 创建
FeedAd对象,设置 delegate,并实现所需的FeedAdDelegate方法。 - 加载广告。
- 创建
FeedAdCollectionViewAdapter并绑定到UICollectionView。
广告信息流集成说明
- 所有 Yandex Mobile Ads SDK 方法须在主线程调用。
- 在展示信息流的界面可见期间,请对
FeedAd与FeedAdCollectionViewAdapter保持强引用。
外观
创建 FeedAdAppearance 配置对象。
可用参数:
cardWidth(必填):展示广告宽度,单位为 point。通常取屏幕宽度减去左右边距。cardCornerRadius:展示广告圆角半径,单位为 point。
let feedMargin: CGFloat = 24
let cardWidth = view.bounds.width - 2 * feedMargin
let appearance = FeedAdAppearance(cardWidth: cardWidth, cardCornerRadius: 16)
加载广告
使用 Yandex Advertising Network 界面获取的广告位 ID(adUnitId)创建 FeedAd。
可通过 AdRequest 扩展请求,传入用户兴趣、页面上下文、位置等数据,有助于提升广告质量。详见广告定位。
设置 delegate,并实现 FeedAdDelegate 以处理加载与广告事件:
final class FeedAdViewController: UIViewController {
private var feedAd: FeedAd?
func loadAd() {
let request = AdRequest(adUnitID: "R-M-XXXXXX-Y")
let appearance = FeedAdAppearance(cardWidth: view.bounds.width)
let feedAd = FeedAd(requestConfiguration: request, appearance: appearance)
feedAd.delegate = self
self.feedAd = feedAd
feedAd.loadAd()
}
}
extension FeedAdViewController: FeedAdDelegate {
func feedAdDidLoad(_ feedAd: FeedAd) {
// Called when an ad is successfully loaded
}
func feedAd(_ feedAd: FeedAd, didFailToLoadWithError error: Error) {
// Called when ad loading fails
}
func feedAdDidClick(_ feedAd: FeedAd) {
// Called when the user taps the ad
}
func feedAd(_ feedAd: FeedAd, didTrackImpression impressionData: ImpressionData?) {
// Called when an impression is tracked
}
func feedAdDidUpdateDataSource(_ feedAd: FeedAd) {
// Called when new ads are available — reload collection view
collectionView.reloadData()
}
}
展示信息流
使用 FeedAdCollectionViewAdapter 作为 UICollectionView 的 dataSource 与 delegate。
在绑定适配器前,调用 registerCells(in:) 注册单元格类型,且须在设置 dataSource 与 delegate 之前完成。
作为主列表
将适配器的 dataSource 与 delegate 赋给 UICollectionView:
final class FeedAdViewController: UIViewController {
private let collectionView = UICollectionView(
frame: .zero,
collectionViewLayout: UICollectionViewFlowLayout()
)
private var feedAdAdapter: FeedAdCollectionViewAdapter?
func setupAdapter() {
guard let feedAd else { return }
let adapter = FeedAdCollectionViewAdapter(feedAd: feedAd)
adapter.registerCells(in: collectionView)
collectionView.dataSource = adapter.dataSource
collectionView.delegate = adapter.delegate
feedAdAdapter = adapter
}
}
与现有内容并存
若已自行实现 UICollectionViewDataSource,可将信息流分区委托给适配器:
final class FeedAdViewController: UIViewController {
private enum Section: Int, CaseIterable {
case content
case feed
}
private var contentItems: [ContentItem] = []
private var feedAdAdapter: FeedAdCollectionViewAdapter?
func setupAdapter() {
guard let feedAd else { return }
let adapter = FeedAdCollectionViewAdapter(feedAd: feedAd)
adapter.registerCells(in: collectionView)
feedAdAdapter = adapter
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension FeedAdViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
Section.allCases.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch Section(rawValue: section) {
case .content:
return contentItems.count
case .feed:
return feedAdAdapter?.dataSource.collectionView(collectionView, numberOfItemsInSection: section) ?? 0
case .none:
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch Section(rawValue: indexPath.section) {
case .content:
// Return your content cell
return dequeueContentCell(for: indexPath)
case .feed:
return feedAdAdapter?.dataSource.collectionView(collectionView, cellForItemAt: indexPath)
?? UICollectionViewCell()
case .none:
return UICollectionViewCell()
}
}
}
extension FeedAdViewController: UICollectionViewDelegateFlowLayout {
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
switch Section(rawValue: indexPath.section) {
case .feed:
return feedAdAdapter?.delegate.collectionView?(
collectionView,
layout: collectionViewLayout,
sizeForItemAt: indexPath
) ?? .zero
default:
return CGSize(width: collectionView.bounds.width, height: 80)
}
}
}
测试广告信息流集成
使用演示广告单元
要验证广告信息流集成并测试应用,请使用测试广告。
为确保每次广告请求都返回测试广告,我们提供了专用的演示广告位 ID,可用于检查集成是否正确。
演示用 adUnitId:demo-feed-yandex。
重要
在将应用发布到商店之前,请将演示广告位 ID 替换为在 Yandex Advertising Network 界面中获取的真实 ID。
完整的演示广告位 ID 列表见用于测试的演示广告单元。
验证集成
您可以使用本机控制台工具测试广告集成。
要查看详细日志,请调用 YMAMobileAds 类的 enableLogging 方法。
YMAMobileAds.enableLogging()
要查看 SDK 日志,请前往控制台工具并设置 Subsystem = com.mobile.ads.ads.sdk。您还可以按类别和错误级别过滤日志。
如果您在集成广告时遇到问题,您将获得有关问题的详细报告以及如何解决这些问题的建议。
更多资源
-
GitHub 链接。