Momento iOS 指南
指南文档更新日期 → 2023.07.10 SDK 版本 → 0.0.2
最低 iOS 开发目标 → Ver.11.0
公共设置项目指南
AppDelegate
- 在 AppDelegate 的下面方法中添加调试模式 ON/OFF 信息。
- True 的情况下连接测试服务器,False 的情况下连接到生产服务器。
在生产部署中使用的情况下,请在参数中添加 False。- 没有设置时自动连接到生产(默认值 = false)。
- 本指南仅供参考,您可以参考 Banner、Native、Video 以及 VC 的示例代码。但并非必须,这只是为了帮助您更方便地应用。您不需要一定要遵循示例进行实现。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
MomentSDK.shared.isDebugMode(true) // <- 테스트서버 ?? 상용서버
return true
}
MomentAdsDelegate
- onAdLoaded(dspName: String)
- 广告加载成功时会调用,可以在此function中定义需要执行的操作。
- onAdShowed(isShown: Bool)
- 广告显示成功时会调用,可以在此function中定义需要执行的操作。
- onAdClicked()
- 点击广告时会调用,可以在此function中定义需要执行的操作。
- onAdFailed(error: Error)
- 广告加载失败时会调用,可以在此function中定义需要执行的操作。
- onAdTimedout()
- 广告加载中发生超时时调用,可以在此function中定义需要执行的操作。
- onAdRemoved()
- 广告被删除时会调用,可以在此function中定义需要执行的操作。
MomentVideoDelegate
- onVideoLoaded(dspName: String)
- 广告视频加载成功时会调用,可以在此function中定义需要执行的操作。
- onVideoStoped()
- 广告视频在中间停止时会调用,可以在此function中定义需要执行的操作。
- onVideoComplete()
- 完全播放广告视频时会调用,可以在此function中定义需要执行的操作。
- onVideoRewarded(state: Bool)
- 在中间关闭奖励式广告视频时被调用,对于插屏式广告视频,不会调用此delegate function。可以在此function中定义需要执行的操作。
onVideoError(description: String)→ Duplicated(0.1.36)广告因任何原因失败时会调用,可以在此function中定义需要执行的操作。
- onVideoTimedout()
- 广告请求超时时调用,可以在此function中定义需要执行的操作。
- onVideoShown()
- 广告正常显示时会调用,可以在此function中定义需要执行的操作。
- onVideoClosed()
- 广告关闭时会调用,可以在此function中定义需要执行的操作。
- onVideoRemoved()
- 广告被删除时会调用,可以在此function中定义需要执行的操作。
- onVideoClicked(type: MomentSDK.videoClickType)
- 点击广告时会调用,可以在此function中定义需要执行的操作。
- onVideoLoadFailed(description: String)
- 广告加载失败时会调用,可以在此function中定义需要执行的操作。
- onVideoShowFailed.description: String)
- 广告显示失败时会调用,可以在此function中定义需要执行的操作。
Banner/Native/Video分别详细设置指南
Banner
-
Banner设置元素
- 分为50 / 100 / 250三种尺寸。定义枚举后使用更方便。
enum bannerSizeEnum: Int { case small = 50 case medium = 100 case large = 250 }
- 可以使用MomentBannerView(size: Int, unitID: String)参数进行初始化。
- 将用于控制MomentBannerView的VC声明为View的Delegate。
- 通过 MomentBannerView 的**loadAd()**可以通过服务器加载广告。
-
MomentAdsDelegate
- 上文中描述的Delegate的函数会根据情况被调用。因此,可以继承MomentAdsDelegate并在其中实现相应的方法来使用。
-
MomentBannerView
-
MomentBannerView使用示例
var sizeEnum: bannerSizeEnum = .small // 50 var moBanner: MomentBannerView? var getUnitID = "" ... if moBanner == nil { moBanner = MomentBannerView(size: sizeEnum.rawValue, unitId: getUnitID) guard let moBanner = moBanner else { return } moBanner.delegate = self getBannerView.addSubview(moBanner) //배너위치에다가 addsubview moBanner.loadAd() } else { moBanner?.loadAd() }
-
Native
-
Native设置元素
- 可使用Xib构建UI和Code构建UI。
- 使用Xib、Code构建UI后,分别在每个View中插入unitID以进行初始化。
- 使用MomentNativeManager的loadWithRendering()连接UI配置元素。
-
通过Xib构建UI的示例
class NativeXibView: UIView { @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var button: UIButton! @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var descriptionLabel: UILabel! @IBOutlet weak var logoImageView: UIImageView! @IBOutlet weak var optionalButton: UIButton! private var getUnitId = "" var manager: MomentNativeManager! @objc public weak var delegate: MomentAdsDelegate? { didSet { manager.delegate = delegate } } @objc public init(unitId: String) { let makeframe = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 300) // 모든 버튼, 사진, 텍스트 등을 담을 프레임의 사이즈 super.init(frame: makeframe) getUnitId = unitId manager = MomentNativeManager(unitId: getUnitId) manager.delegate = delegate let adView = Bundle.main.loadNibNamed("NativeXibView", owner: self, options: nil)?.first as? UIView self.addSubview(adView!) self.backgroundColor = .clear } @objc public func loadAd() { manager.loadWithRendering(mainImageView: imageView, logoImageView: logoImageView, titleLabel: titleLabel, descriptionLabel: descriptionLabel, button: button, optionalButton: optionalButton, timeOut: 10) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @objc public func destory() { delegate?.onAdRemoved() } }
-
通过Code构建UI的示例
class NativeTestView: UIView { /* View를 구성하는 라이브러리를 사용하지 않는 경우 */ var mainImageView = UIImageView() var stackH = UIStackView() var stackV = UIStackView() var logoImageView = UIImageView() var titleLabel = UILabel() var descriptionLabel = UILabel() var button = UIButton() var optionalButton = UIButton() /* SnapKit과 Then을 사용하여 View를 구성하는 경우, 아래의 With SnapKit + Then 주석을 참고하여 적용할 수 있습니다. */ var mainImageView: UIImageView! var stackH: UIStackView! var stackV: UIStackView! var logoImageView: UIImageView! var titleLabel: UILabel! var descriptionLabel: UILabel! var button: UIButton! var optionalButton: UIButton! private var getUnitId = "" var manager: MomentNativeManager! @objc public weak var delegate: MomentAdsDelegate? { didSet { manager.delegate = delegate } } @objc public init(unitId: String) { let makeframe = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 300) // 모든 버튼, 사진, 텍스트 등을 담을 프레임의 사이즈 super.init(frame: makeframe) getUnitId = unitId manager = MomentNativeManager(unitId: getUnitId) manager.delegate = delegate } @objc public func loadAd() { if mainImageView == nil { setupWithLayout() } // With SnapKit + Then manager.loadWithRendering(mainImageView: mainImageView, logoImageView: logoImageView, titleLabel: titleLabel, descriptionLabel: descriptionLabel, button: button, optionalButton: optionalButton, timeOut: 10) setupView() // Without SnapKit + Then layout() // Without SnapKit + Then } @objc public func destory() { delegate?.onAdRemoved() } required init?(coder: NSCoder) { super.init(coder: coder) } deinit { print("Deinit") } //MARK: - Using SnapKit + Then private func setupWithLayout() { if titleLabel != nil { titleLabel.text = "" } mainImageView = UIImageView().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.clipsToBounds = true $0.contentMode = .scaleAspectFit self.addSubview($0) $0.snp.makeConstraints { $0.width.equalTo(300) $0.height.equalTo(115) $0.top.equalToSuperview() } } stackH = UIStackView().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.clipsToBounds = true $0.axis = .horizontal $0.spacing = 8 $0.distribution = .fill self.addSubview($0) $0.snp.makeConstraints { $0.height.equalTo(40) $0.top.equalTo(mainImageView.snp.bottom).offset(25) $0.leading.trailing.equalTo(mainImageView).offset(12) } } logoImageView = UIImageView().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.clipsToBounds = true $0.contentMode = .scaleAspectFit stackH.addArrangedSubview($0) $0.snp.makeConstraints { $0.width.height.equalTo(40) } } stackV = UIStackView().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.clipsToBounds = true $0.axis = .vertical $0.spacing = 2 $0.distribution = .equalSpacing stackH.addArrangedSubview($0) } titleLabel = UILabel().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.font = UIFont.boldSystemFont(ofSize: 13.0) $0.numberOfLines = 1 stackV.addArrangedSubview($0) } descriptionLabel = UILabel().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.font = UIFont.boldSystemFont(ofSize: 13.0) $0.numberOfLines = 1 stackV.addArrangedSubview($0) } button = UIButton().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.setTitle("보러가기", for: .normal) $0.clipsToBounds = true $0.backgroundColor = .blue self.addSubview($0) $0.snp.makeConstraints { $0.width.equalTo(mainImageView.snp.width) $0.height.equalTo(42) $0.top.equalTo(stackH.snp.bottom).offset(25) } } optionalButton = UIButton().then { $0.translatesAutoresizingMaskIntoConstraints = false $0.backgroundColor = .clear $0.clipsToBounds = true self.addSubview($0) $0.snp.makeConstraints { $0.top.bottom.equalTo(self.safeAreaLayoutGuide) $0.leading.trailing.equalTo(mainImageView) } } } //MARK: - Using Swift Constraints func setupView() { backgroundColor = .clear mainImageView.translatesAutoresizingMaskIntoConstraints = false mainImageView.clipsToBounds = true mainImageView.contentMode = .scaleAspectFit self.addSubview(mainImageView) stackH.translatesAutoresizingMaskIntoConstraints = false stackH.clipsToBounds = true stackH.axis = .horizontal stackH.spacing = 8 stackH.distribution = .fill self.addSubview(stackH) logoImageView.translatesAutoresizingMaskIntoConstraints = false logoImageView.clipsToBounds = true logoImageView.contentMode = .scaleAspectFit stackH.addArrangedSubview(logoImageView) stackV.translatesAutoresizingMaskIntoConstraints = false stackV.clipsToBounds = true stackV.axis = .vertical stackV.spacing = 2 stackV.distribution = .equalSpacing stackH.addArrangedSubview(stackV) titleLabel.translatesAutoresizingMaskIntoConstraints = false titleLabel.font = UIFont.boldSystemFont(ofSize: 13.0) titleLabel.numberOfLines = 1 stackV.addArrangedSubview(titleLabel) descriptionLabel.translatesAutoresizingMaskIntoConstraints = false descriptionLabel.font = UIFont.boldSystemFont(ofSize: 13.0) descriptionLabel.numberOfLines = 1 stackV.addArrangedSubview(descriptionLabel) button.translatesAutoresizingMaskIntoConstraints = false button.setTitle("보러가기", for: .normal) button.clipsToBounds = true button.backgroundColor = .blue self.addSubview(button) optionalButton.translatesAutoresizingMaskIntoConstraints = false optionalButton.backgroundColor = .clear optionalButton.clipsToBounds = true self.addSubview(optionalButton) } func layout() { guard let superview = self.superview else { return } mainImageView.widthAnchor.constraint(equalToConstant: 300).isActive = true mainImageView.heightAnchor.constraint(equalToConstant: 115).isActive = true mainImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true stackH.heightAnchor.constraint(equalToConstant: 40).isActive = true stackH.topAnchor.constraint(equalTo: mainImageView.bottomAnchor, constant: 25).isActive = true stackH.leadingAnchor.constraint(equalTo: mainImageView.leadingAnchor, constant: 12).isActive = true stackH.trailingAnchor.constraint(equalTo: mainImageView.trailingAnchor, constant: -12).isActive = true logoImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true logoImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true button.widthAnchor.constraint(equalTo: mainImageView.widthAnchor).isActive = true button.heightAnchor.constraint(equalToConstant: 42).isActive = true button.topAnchor.constraint(equalTo: stackH.bottomAnchor, constant: 25).isActive = true optionalButton.topAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.topAnchor).isActive = true optionalButton.leadingAnchor.constraint(equalTo: mainImageView.leadingAnchor).isActive = true optionalButton.trailingAnchor.constraint(equalTo: mainImageView.trailingAnchor).isActive = true optionalButton.bottomAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.bottomAnchor).isActive = true } }
- 使用Code构建UI的情况下,也存在使用SnapKit + Then的示例代码。
-
MomentAdsDelegate
- 上文中描述的Delegate的函数会根据情况被调用。因此,可以继承MomentAdsDelegate并在其中实现相应的方法来使用。
-
MomentNativeManager
- 无论是Xib方式还是Code方式,都需要声明MomentNativeManager类型的manager,然后调用loadWithRendering()方法。
- loadWithRendering()的参数中,除了按钮和时间超时(timeOut)外,其它元素都是可选的,开发者可以选择是否使用。例如,如果不使用用于加载logo图像的UIImageView,则可以将其设置为nil。
时间超时(timeOut)的默认值为15秒。如果不添加任何值,则默认为15秒;如果有特定的时间,可以添加以在相应的时间内没有响应时调用Delegate的onAdTimedout()。
- 更详细的内容可以通过loadWithRendering()的快速帮助方法(opt + click)来查看。
class NativeTestVC: UIViewController { var size = 300 var xibNative: NativeXibView? var moNative: NativeTestView? var getUnitID = "" ... switch sender.tag { case 21: if moNative != nil { moNative?.removeFromSuperview() moNative = nil } if xibNative == nil { xibNative = NativeXibView(unitId: getUnitID) guard let xibNative else { return } xibNative.delegate = self getNativeView.addSubview(xibNative) // 메인뷰와 연결 xibNative.loadAd() } else { xibNative?.loadAd() } case 22: if xibNative != nil { xibNative?.removeFromSuperview() xibNative = nil } if moNative == nil { moNative = NativeTestView(unitId: getUnitID) guard let moNative else { return } moNative.delegate = self getNativeView.addSubview(moNative) // 메인뷰와 연결 moNative.loadAd() } else { moNative?.loadAd() } default: break } }
Video
-
视频设置元素及MomentVideoManager
- 对于视频,可以独立使用loadVideo()和showVideo()。
- loadVideo()可以预先加载视频广告,而showVideo()可以显示已加载的广告。
- 在showVideo()中,视频播放完毕后,用户点击close按钮触发事件,**将自动加载一个广告**。
- 通过VideoManager的hasVideoAd()方法可以检查是否有广告。
- 在ViewController中声明继承自MomentVideoManager的变量。在声明变量的时间插入unitID。
- 将该变量的videoDelegate设置为self,之后在需要的时间调用loadVideo()和showVideo()。
- 示例
class VideoTestVC: UIViewController { ... var getUnitID: String = "" var moVideo: MomentVideoManager? ... @IBAction func bannerAct(_ sender: UIButton) { switch sender.tag { case 20: for subview in getStackView.arrangedSubviews { subview.removeFromSuperview() } case 21: if moVideo == nil { moVideo = MomentVideoManager(unitID: getUnitID) <- guard let moVideo = moVideo else { return } moVideo.videoDelegate = self <- moVideo.loadVideo() <- } else { moVideo?.loadVideo() } case 22: guard let moVideo = moVideo else { return } moVideo.videoDelegate = self moVideo.showVideo() <- ... default: break } } ... }
- 对于视频,可以独立使用loadVideo()和showVideo()。
-
MomentVideoDelegate
- 上文中描述的Delegate的函数会根据情况被调用。因此,可以继承MomentVideoDelegate并在其中实现相应的方法来使用。
GDPR 집해제 가이드
MomentoiOS SDK GDPR 집해제 미니멘트 버전 → 0.1.32
本指南是为遵守GDPR的媒体制作的。
通过MomentSDK的内部方法setTCString(:String)传递TCString。
MomentSDK.shared.setTCString(TCSTring: "E1X2A3M4P5L6E7")
根据用户GDPR的同意与否,将接收到的result value传递给用户。
如果用户不同意,请将setTCString参数传递空白字符串“”。