This is a user behavior tracking (UBT) tool to analyze impression events for UIView (exposure of UIView) in iOS.
How it works: Hook the didMoveToWindow method of a UIView by SwiftHook, periodically check the view is on the screen or not.
It's quite simple.
// UIKit
UIView().detectImpression { (view, state) in
if state.isImpressed {
print("This view is impressed to users.")
}
}
// SwiftUI
Color.red.detectImpression { state in
if state.isImpressed {
print("This view is impressed to users.")
}
}Use ImpressionGroup for UICollectionView, UITableView, List or other reusable view cases.
// UIKit
var group = ImpressionGroup.init {(_, index: IndexPath, view, state) in
if state.isImpressed {
print("impressed index: \(index.row)")
}
}
...
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
self.group.bind(view: cell, index: indexPath)
return cell
}
// SwiftUI
var group = ImpressionGroup.init { (_, index: Int, _, state) in
if state.isImpressed {
print("impressed index: \(index)")
}
}
var body: some View {
List(0 ..< 100) { index in
CellView(index: index)
.frame(height: 100)
.detectImpression(group: group, index: index)
}
}Modify the detection (scan) interval (in seconds). Smaller detectionInterval means higher accuracy and higher CPU consumption.
UIView.detectionInterval = 0.1 // apply to all views
UIView().detectionInterval = 0.1 // apply to the specific view. `UIView.detectionInterval` will be used if it's nil.
ImpressionGroup().detectionInterval = 0.1 // apply to the group. `UIView.detectionInterval` will be used if it's nil.Modify the threshold (seconds) for the duration of a view on the screen. If the view's duration on the screen exceeds this threshold, it may trigger an impression.
UIView.durationThreshold = 2 // apply to all views
UIView().durationThreshold = 2 // apply to the specific view. `UIView.durationThreshold` will be used if it's nil.
ImpressionGroup().durationThreshold = 2 // apply to the group. `UIView.durationThreshold` will be used if it's nil.Modify the threshold (from 0 to 1) for the area ratio of the view on the screen. If the percentage of the view's area on the screen exceeds this threshold, it may trigger an impression.
UIView.areaRatioThreshold = 0.4 // apply to all views
UIView().areaRatioThreshold = 0.4 // apply to the specific view. `UIView.areaRatioThreshold` will be used if it's nil.
ImpressionGroup().areaRatioThreshold = 0.4 // apply to the group. `UIView.areaRatioThreshold` will be used if it's nil.Modify the threshold (from 0 to 1) for the view opacity. If the view's opacity exceeds this threshold, it may trigger an impression.
UIView.alphaThreshold = 0.4 // apply to all views
UIView().alphaThreshold = 0.4 // apply to the specific view. `UIView.alphaThreshold` will be used if it's nil.
ImpressionGroup().alphaThreshold = 0.4 // apply to the group. `UIView.alphaThreshold` will be used if it's nil.Retrigger the impression event in some situations.
// Retrigger the impression event when a view left from the screen (The UIViewController (page) is still here, Just the view is out of the screen).
public static let leftScreen = Redetect(rawValue: 1 << 0)
// Retrigger the impression event when the UIViewController of the view disappear.
public static let viewControllerDidDisappear = Redetect(rawValue: 1 << 1)
// Retrigger the impression event when the App did enter background.
public static let didEnterBackground = Redetect(rawValue: 1 << 2)
// Retrigger the impression event when the App will resign active.
public static let willResignActive = Redetect(rawValue: 1 << 3)UIView.redetectOptions = [.leftScreen, .viewControllerDidDisappear, .didEnterBackground, .willResignActive] // apply to all views
UIView().redetectOptions = [.leftScreen, .viewControllerDidDisappear, .didEnterBackground, .willResignActive] // apply to the specific view. `UIView.redetectOptions` will be used if it's nil.
ImpressionGroup().redetectOptions = [.leftScreen, .viewControllerDidDisappear, .didEnterBackground, .willResignActive] // apply to the group. `UIView.redetectOptions` will be used if it's nil.Refer to the Demo for more details.
ImpressionKit can be integrated by cocoapods.
pod 'ImpressionKit'
Or use Swift Package Manager. SPM is supported from 3.1.0.
- iOS 12.0+ (UIKit)
- iOS 13.0+ (SwiftUI)
- Xcode 15.1+
