Skip to content

iOS 原生广告集成

概述

原生广告采用自渲染模式:开发者自行绘制广告视图,通过 NativeAdViewBinder 绑定视图、NativeAdData 填充物料。

iOS 与 Android 的差异

iOS 自渲染采用 view.tag 模式标识组件(替代 Android 的 R.id 资源 ID)。通过为每个子视图设置唯一 tag,再在 NativeAdViewBinder 中传入对应 tag 完成绑定。

集成步骤

1. 创建并加载原生广告

swift
import UIKit
import UjuAdCore

final class NativeAdHelper {
    private var nativeAd: UjuAdObject?

    func load(vc: UIViewController, container: UIView) {
        let config = UjuAdConfig(
            placementId: "YOUR_NATIVE_PLACEMENT_ID",
            adViewSize: AdViewSize.nativeSize690x388  // 信息流卡片尺寸
        )
        let native = UjuAdObject.getNativeObject(vc, config: config)
        native.setAdObjectListener(NativeListener(helper: self, container: container, vc: vc))
        self.nativeAd = native
        native.load()
    }

    func destroy() {
        nativeAd?.destroy()
        nativeAd = nil
    }
}

2. 实现原生监听器并渲染

swift
final class NativeListener: FeedAdObjectListener, @unchecked Sendable {
    private weak var helper: NativeAdHelper?
    private weak var container: UIView?
    private weak var vc: UIViewController?

    init(helper: NativeAdHelper, container: UIView, vc: UIViewController) {
        self.helper = helper
        self.container = container
        self.vc = vc
    }

    func onLoadSuccess() {
        guard let nativeAd = helper?.nativeAd, let vc = vc, let container = container else { return }
        // 自渲染:获取物料数据并绑定视图
        renderNativeAd(ad: nativeAd, vc: vc, container: container)
    }

    func onLoadError(error: UjuException) {
        print("原生广告加载失败: \(error.description)")
    }

    func onAdShow() {}
    func onAdClicked() {}
    func onAdClosed() {}
    func onLpClosed() {}
    func onAdError(error: UjuException) {
        print("原生广告展示错误: \(error.description)")
    }

    private func renderNativeAd(ad: UjuAdObject, vc: UIViewController, container: UIView) {
        // 详见下方「自渲染示例」
    }
}

自渲染示例

swift
private func renderNativeAd(ad: UjuAdObject, vc: UIViewController, container: UIView) {
    // 1. 获取物料数据
    guard let data = ad.getAdData() else { return }

    // 2. 创建视图,并为每个子视图设置唯一 tag
    let adView = UIView()

    let titleLabel = UILabel()
    titleLabel.tag = 101

    let descLabel = UILabel()
    descLabel.tag = 102

    let iconImageView = UIImageView()
    iconImageView.tag = 103

    let mainImageView = UIImageView()
    mainImageView.tag = 104

    let ctaButton = UIButton(type: .system)
    ctaButton.tag = 105

    adView.addSubview(titleLabel)
    adView.addSubview(descLabel)
    adView.addSubview(iconImageView)
    adView.addSubview(mainImageView)
    adView.addSubview(ctaButton)
    // ... 设置 Auto Layout 约束 ...

    // 3. 构造 binder(view.tag 模式,仅 titleTag 必填,其余默认 0 表示不绑定)
    let binder = NativeAdViewBinder(
        titleTag: 101,
        descTag: 102,
        sourceTag: 0,          // 0 表示不绑定来源
        imageTag: 104,         // 主图
        mediaViewTag: 0,       // 视频物料时绑定
        iconTag: 103,          // 图标
        callToActionTag: 105,
        logoTag: 0,
        clickViewTags: [104],  // 主图可点击
        dislikeTag: 0
    )

    // 4. 注册视图用于交互(SDK 会自动填充数据 + 绑定点击手势)
    ad.registerViewForInteraction(vc: vc, adView: adView, container: container, binder: binder)
    ad.show(vc, container: container)
}

NativeAdData 字段

UjuAdObject.getAdData() 返回 NativeAdData?,用于自渲染填充数据,所有字段均为可选:

字段类型说明
titleString?广告标题
descString?广告描述
sourceString?广告来源
callToActionString?行动号召文案(如「立即下载」)
imageUrlString?单图 URL
imageUrlList[String]?多图 URL 列表(>1 张时)
iconUrlString?图标 URL

如需自行处理数据(不使用 binder 模式):

swift
if let data = ad.getAdData() {
    print("title: \(data.title ?? "")")
    print("icon: \(data.iconUrl ?? "")")
    // 自行下载图片并渲染
}

NativeAdViewBinder 字段

NativeAdViewBinder 用于自渲染绑定视图,采用 view.tag 模式。仅 titleTag 必填,其余字段默认 0(或空数组)表示不绑定:

字段类型必填默认值说明
titleTagInt标题视图 tag
descTagInt0描述视图 tag
sourceTagInt0来源视图 tag
imageTagInt0主图视图 tag
mediaViewTagInt0媒体视图 tag(视频广告)
iconTagInt0图标视图 tag
callToActionTagInt0行动号召按钮 tag
logoTagInt0广告标识 tag
clickViewTags[Int][]额外可点击视图 tag 列表
dislikeTagInt0不感兴趣按钮 tag

最佳实践

  1. tag 唯一性:自渲染时确保每个子视图 tag 在 adView 范围内唯一,避免与系统 tag 冲突
  2. 空指针保护NativeAdData 字段均为可选,使用前做 ?? "" 兜底
  3. 资源释放:cell 复用或视图移除时调用 destroy()
  4. 图片加载:自行下载 imageUrl / iconUrl,建议使用 SDWebImage / Kingfisher 等库

常见问题

Q: 自渲染视图为什么不显示数据?

A: 可能的原因:

  • NativeAdViewBindertag 与视图实际 tag 不匹配
  • 未调用 registerViewForInteraction(vc:adView:container:binder:) 注册交互
  • 容器视图尺寸为 0 或未加入视图层级
  • getAdData() 返回 nil(非 native 类型调用)

相关链接