Customizing an existing view controller by subclassing the default implementation
Subclassing an existing view controller helps when:
- adding features on top of the existing one
- logs
- Adding new UI elements
- Removing existing UI elements
- keeping the existing behaviour while providing custom UI.
The following view controllers can be subclassed:
- FormViewController
- GenericViewController
- PollingViewController
- ProblemViewController
- SelectorViewController
- WebAuthnViewController
- BaseViewController
The following examples illustrate this customization option:
- Subclassing
SelectorViewControllerto display an advertisement banner at the top of the screen. - Subclassing
FormViewControllerto trigger reCAPTCHA when a button is pushed.
Subclassing SelectorViewController to display an advertisement banner at the top of the screen.
Follow the prerequisite to import the Google Mobile Ads SDK dependency and set up the mandatory configuration.
The info.plist looks like that:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4fzdc2evr5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>2fnua5tdw4.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ydx93a7ass.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>p78axxw29g.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v72qych5uu.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ludvb6z3bs.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cp8zw746q7.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3sh42y64q3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>c6k4g5qg8m.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>s39g8k73mm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3qy4746246.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>hs6bdukanm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>mlmmfzh3r3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v4nxqhlyqp.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>wzmmz9fp6w.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>su67r6k2v3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>yclnxrl5pm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>7ug5zh24hu.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>gta9lk7p23.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>vutu7akeur.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>y5ghdn5j9k.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v9wttpbfk9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>n38lu8286q.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>47vhws6wlr.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>kbd757ywx3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>9t245vhmpl.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>a2p9lx4jpn.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>22mmun2rn5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4468km3ulz.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>2u9pt9hc89.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>8s468mfl3y.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ppxm28t8ap.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>uw77j35x4d.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>pwa73g5rt2.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>578prtvx9j.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4dzt52r2t5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>tl55sbb4fm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>e5fvkxwrpn.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>8c4e2ghe7u.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3rd42ekr43.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3qcr597p9d.skadnetwork</string>
</dict>
</array>
</dict>
</plist>
In your AppDelegate, the Mobile Ads SDK has to be configured as demonstrated in the following snippet.
import GoogleMobileAds
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// GoogleMobileAds
MobileAds.shared.start(completionHandler: nil)
return true
}
}
Create a subclass of SelectorViewController that will display a banner Ads as demonstrated below.
import Foundation
import IdsvrHaapiUIKit
import GoogleMobileAds
class AdsSelectorViewController: SelectorViewController {
var bannerView: AdManagerBannerView!
override func viewDidLoad() {
super.viewDidLoad()
let adSize = currentOrientationAnchoredAdaptiveBanner(width: view.bounds.width)
bannerView = AdManagerBannerView(adSize: adSize)
bannerView.adUnitID = "ca-app-pub-3940256099942544/2435281174"
bannerView.rootViewController = self
bannerView.load(Request())
insertView(bannerView, aboveView: messagesStackView)
}
}
In your AppDelegate, create an instance of ViewControllerFactoryRegistry and set to your HaapiUIKitApplicationBuilder as demonstrated below:
import GoogleMobileAds
import IdsvrHaapiUIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// GoogleMobileAds
MobileAds.shared.start(completionHandler: nil)
// Registering the custom SelectorViewController to render SelectorModel
let resolver = ViewControllerFactoryRegistry()
.registerViewControllerFactorySelectorModel { model, style, commonStyle in
return AdsSelectorViewController(model, style: style, commonStyle: commonStyle)
}
do {
haapiUIKitApplication = try HaapiUIKitApplicationBuilder(haapiUIKitConfiguration: haapiUIKitConfiguration)
.setViewControllerFactoryRegistry(registry: resolver)
.buildOrThrow()
} catch {
print("An exception was thrown and it should be handled.: \(error)")
}
return true
}
}
When starting the HAAPI flow and the SelectorModel is displayed, a banner view is presented at the top of the screen as demonstrated below.
Subclassing FormViewController to trigger reCAPTCHA when a button is pushed.
Follow the prerequisite to import reCAPTCHA dependency and set up the mandatory configuration.
Create a subclass of FormViewController that will handle reCaptcha when the user submits an action.
import Foundation
import IdsvrHaapiUIKit
import RecaptchaEnterprise
class ReCaptchaFormViewController: FormViewController {
var recaptchaClient: RecaptchaClient!
override func viewDidLoad() {
super.viewDidLoad()
Task {
do {
self.recaptchaClient = try await Recaptcha.fetchClient(withSiteKey: "6LfqguwqADAAADw4QGR3arg4q0SfB4Y6wtu4kHaf")
} catch let error as RecaptchaError {
print(error)
}
}
}
override func preSubmit(interactionActionModel: any InteractionActionModel,
parameters: [String : Any],
closure: @escaping (Bool, [String : Any]) -> Void)
{
recaptchaClient.execute(withAction: RecaptchaAction.login) { token, error in
let willSubmit: Bool
if let token = token {
print(token)
willSubmit = true
}
if let error = error {
print(error)
willSubmit = false
}
closure(willSubmit, parameters)
}
}
}
In your AppDelegate, create an instance of ViewControllerFactoryRegistry and set to your HaapiUIKitApplicationBuilder as demonstrated below:
import IdsvrHaapiUIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Registering the custom ReCaptchaFormViewController to render FormModel
let resolver = ViewControllerFactoryRegistry()
.registerViewControllerFactoryFormModel { model, style, commonStyle in
return ReCaptchaFormViewController(model, style: style, commonStyle: commonStyle)
}
do {
haapiUIKitApplication = try HaapiUIKitApplicationBuilder(haapiUIKitConfiguration: haapiUIKitConfiguration)
.setViewControllerFactoryRegistry(registry: resolver)
.buildOrThrow()
} catch {
print("An exception was thrown and it should be handled.: \(error)")
}
return true
}
}
When ReCaptchaFormViewController is presented and the button is pressed. Before submiting the form, a reCAPTCHA flow is triggered. When identifying successfully as a human, then the block of the submitting button is sent.