Skip to content

Commit ef62985

Browse files
πŸ§‘β€πŸ’» Implement Objective-C sample
1 parent 60ff075 commit ef62985

32 files changed

+1608
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// AppDelegate.h
3+
// ObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import <UIKit/UIKit.h>
9+
@import Userpilot;
10+
11+
@interface AppDelegate : UIResponder <UIApplicationDelegate, UserpilotExperienceDelegate, UserpilotNavigationDelegate, UserpilotAnalyticsDelegate>
12+
13+
14+
@end
15+
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//
2+
// AppDelegate.m
3+
// ObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import "AppDelegate.h"
9+
@import Userpilot;
10+
11+
@interface AppDelegate ()
12+
13+
@property (strong, nonatomic) Userpilot *userpilot;
14+
15+
@end
16+
17+
@implementation AppDelegate
18+
19+
20+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
21+
// Override point for customization after application launch.
22+
23+
return YES;
24+
}
25+
26+
27+
#pragma mark - UISceneSession lifecycle
28+
29+
30+
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
31+
// Called when a new scene session is being created.
32+
// Use this method to select a configuration to create the new scene with.
33+
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
34+
}
35+
36+
37+
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
38+
// Called when the user discards a scene session.
39+
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
40+
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
41+
}
42+
43+
44+
#pragma mark - UserpilotExperienceDelegate
45+
46+
- (void)onExperienceStateChangedWithExperienceType:(UserpilotExperienceType)experienceType
47+
experienceId:(NSNumber *)experienceId
48+
experienceState:(UserpilotExperienceState)experienceState {
49+
NSLog(@"Experience [%@] type: %ld changed state to: %ld",
50+
experienceId, (long)experienceType, (long)experienceState);
51+
}
52+
53+
- (void)onExperienceStepStateChangedWithExperienceType:(UserpilotExperienceType)experienceType
54+
experienceId:(NSNumber *)experienceId
55+
stepId:(NSNumber *)stepId
56+
stepState:(UserpilotExperienceState)stepState
57+
step:(NSNumber *)step
58+
totalSteps:(NSNumber *)totalSteps {
59+
NSLog(@"Step [%@] of experience [%@] (type: %ld) changed state to: %ld - step %d/%d",
60+
stepId, experienceId, (long)experienceType, (long)stepState,
61+
step.intValue, totalSteps.intValue);
62+
}
63+
64+
#pragma mark - UserpilotNavigationDelegate
65+
66+
- (void)navigateTo:(NSURL *)url {
67+
NSLog(@"Userpilot requested navigation to URL: %@", url.absoluteString);
68+
69+
// Example: open the URL externally in Safari
70+
if ([[UIApplication sharedApplication] canOpenURL:url]) {
71+
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
72+
}
73+
74+
// Or if you want to handle specific URLs in-app, use conditionals here
75+
// e.g., check url.host or pathComponents
76+
}
77+
78+
#pragma mark - UserpilotAnalyticsDelegate
79+
80+
- (void)didTrackWithAnalytic:(UserpilotAnalytic)analytic
81+
value:(NSString *)value
82+
properties:(NSDictionary<NSString *, id> *)properties {
83+
NSLog(@"Tracked event - type: %ld, value: %@, properties: %@", (long)analytic, value, properties);
84+
}
85+
86+
87+
@end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// SceneDelegate.h
3+
// ObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import <UIKit/UIKit.h>
9+
10+
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
11+
12+
@property (strong, nonatomic) UIWindow * window;
13+
14+
@end
15+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//
2+
// SceneDelegate.m
3+
// UserpilotObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import "SceneDelegate.h"
9+
#import "Userpilot+Shared.h"
10+
11+
@interface SceneDelegate ()
12+
13+
@end
14+
15+
@implementation SceneDelegate
16+
17+
18+
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
19+
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
20+
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
21+
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
22+
}
23+
24+
25+
- (void)sceneDidDisconnect:(UIScene *)scene {
26+
// Called as the scene is being released by the system.
27+
// This occurs shortly after the scene enters the background, or when its session is discarded.
28+
// Release any resources associated with this scene that can be re-created the next time the scene connects.
29+
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
30+
}
31+
32+
33+
- (void)sceneDidBecomeActive:(UIScene *)scene {
34+
// Called when the scene has moved from an inactive state to an active state.
35+
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
36+
}
37+
38+
39+
- (void)sceneWillResignActive:(UIScene *)scene {
40+
// Called when the scene will move from an active state to an inactive state.
41+
// This may occur due to temporary interruptions (ex. an incoming phone call).
42+
}
43+
44+
45+
- (void)sceneWillEnterForeground:(UIScene *)scene {
46+
// Called as the scene transitions from the background to the foreground.
47+
// Use this method to undo the changes made on entering the background.
48+
}
49+
50+
51+
- (void)sceneDidEnterBackground:(UIScene *)scene {
52+
// Called as the scene transitions from the foreground to the background.
53+
// Use this method to save data, release shared resources, and store enough scene-specific state information
54+
// to restore the scene back to its current state.
55+
}
56+
57+
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
58+
59+
}
60+
61+
62+
@end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// Userpilot+Shared.h
3+
// UserpilotObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import <UIKit/UIKit.h>
9+
@import Userpilot;
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@interface Userpilot (Shared)
14+
+ (Userpilot *)shared;
15+
@end
16+
17+
NS_ASSUME_NONNULL_END
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// Userpilot+Shared.m
3+
// UserpilotObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import "Userpilot+Shared.h"
9+
10+
static Userpilot *sharedInstance = nil;
11+
12+
@implementation Userpilot (Shared)
13+
14+
+ (Userpilot *)shared
15+
{
16+
if (sharedInstance == nil) {
17+
Config *config = [[Config alloc] initWithToken:@"<#TOKEN#>"];
18+
[config loggingWithEnabled:YES];
19+
20+
sharedInstance = [[Userpilot alloc] initWithConfig:config];
21+
}
22+
23+
return sharedInstance;
24+
}
25+
@end
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3+
<device id="retina6_1" orientation="portrait" appearance="light"/>
4+
<dependencies>
5+
<deployment identifier="iOS"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
7+
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
8+
<capability name="System colors in document resources" minToolsVersion="11.0"/>
9+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
10+
</dependencies>
11+
<scenes>
12+
<!--View Controller-->
13+
<scene sceneID="EHf-IW-A2E">
14+
<objects>
15+
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
16+
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
17+
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
18+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19+
<subviews>
20+
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="logo" translatesAutoresizingMaskIntoConstraints="NO" id="5FA-Fb-EY8">
21+
<rect key="frame" x="40" y="391.5" width="334" height="123"/>
22+
</imageView>
23+
</subviews>
24+
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
25+
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
26+
<constraints>
27+
<constraint firstItem="5FA-Fb-EY8" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="12H-vB-jbV"/>
28+
<constraint firstItem="5FA-Fb-EY8" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="40" id="J5j-NW-czA"/>
29+
<constraint firstItem="5FA-Fb-EY8" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" id="Z1n-TS-01c"/>
30+
</constraints>
31+
</view>
32+
</viewController>
33+
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
34+
</objects>
35+
<point key="canvasLocation" x="53" y="375"/>
36+
</scene>
37+
</scenes>
38+
<resources>
39+
<image name="logo" width="581.0999755859375" height="123.08000183105469"/>
40+
<systemColor name="systemBackgroundColor">
41+
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
42+
</systemColor>
43+
</resources>
44+
</document>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// EventsViewController.h
3+
// UserpilotObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import <UIKit/UIKit.h>
9+
10+
NS_ASSUME_NONNULL_BEGIN
11+
12+
@interface EventsViewController : UIViewController
13+
14+
@end
15+
16+
NS_ASSUME_NONNULL_END
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//
2+
// EventsViewController.m
3+
// UserpilotObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import "EventsViewController.h"
9+
#import "Userpilot+Shared.h"
10+
11+
@interface EventsViewController ()
12+
13+
@end
14+
15+
@implementation EventsViewController
16+
17+
- (void)viewDidLoad {
18+
[super viewDidLoad];
19+
// Do any additional setup after loading the view.
20+
}
21+
22+
- (void)viewDidAppear:(BOOL)animated {
23+
[super viewDidAppear:animated];
24+
25+
[[Userpilot shared] screen:@"events"];
26+
}
27+
28+
- (IBAction)buttonOneTapped:(UIButton *)sender {
29+
[[Userpilot shared] trackWithEventName:@"event1" properties:@{
30+
@"demo_key": @"event value"
31+
}];
32+
}
33+
34+
- (IBAction)buttonTwoTapped:(UIButton *)sender {
35+
[[Userpilot shared] trackWithEventName:@"event2" properties:nil];
36+
}
37+
38+
@end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// SignInViewController.h
3+
// UserpilotObjcExample
4+
//
5+
// Created by Motasem Hamed on 17/07/2025.
6+
//
7+
8+
#import <UIKit/UIKit.h>
9+
10+
NS_ASSUME_NONNULL_BEGIN
11+
12+
@interface IdentifyViewController : UIViewController
13+
14+
@end
15+
16+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
Β (0)