@@ -15,6 +15,108 @@ import IterableSDK
1515class  AppDelegate :  UIResponder ,  UIApplicationDelegate  { 
1616    var  window :  UIWindow ? 
1717
18+     // MARK: - AppDelegate Lifecycle
19+     
20+     func  application( _ application:  UIApplication ,  didFinishLaunchingWithOptions launchOptions:  [ UIApplication . LaunchOptionsKey :  Any ] ? )  ->  Bool  { 
21+         // Create window and set root to HomeViewController programmatically for a clean test UI
22+         window =  UIWindow ( frame:  UIScreen . main. bounds) 
23+         let  root  =  UINavigationController ( rootViewController:  HomeViewController ( ) ) 
24+         window? . rootViewController =  root
25+         window? . makeKeyAndVisible ( ) 
26+ 
27+         setupNotifications ( ) 
28+         setupTestModeUI ( ) 
29+         
30+         // Start network monitoring
31+         NetworkMonitor . shared. startMonitoring ( ) 
32+         
33+         // Reset device token session state on app launch for clean testing
34+         AppDelegate . resetDeviceTokenSessionState ( ) 
35+ 
36+         return  true 
37+     } 
38+     
39+     func  applicationWillResignActive( _:  UIApplication )  { 
40+         // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
41+         // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
42+     } 
43+     
44+     func  applicationDidEnterBackground( _:  UIApplication )  { 
45+         // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
46+         // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
47+     } 
48+     
49+     func  applicationWillEnterForeground( _:  UIApplication )  { 
50+         // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
51+     } 
52+     
53+     func  applicationDidBecomeActive( _ application:  UIApplication )  { 
54+         print ( " 🚀 BREAKPOINT HERE: App became active " ) 
55+         // Set a breakpoint here to confirm app is opening
56+         
57+         // App is always in test mode - no validation needed
58+     } 
59+     
60+     func  applicationWillTerminate( _:  UIApplication )  { 
61+         // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
62+     } 
63+     
64+     // MARK: - Silent Push for in-app
65+     
66+     func  application( _ application:  UIApplication ,  didReceiveRemoteNotification userInfo:  [ AnyHashable :  Any ] ,  fetchCompletionHandler completionHandler:  @escaping  ( UIBackgroundFetchResult )  ->  Void )  { 
67+         print ( " 🔕 [APP] Silent push notification received " ) 
68+         print ( " 🔕 [APP] Silent push payload:  \( userInfo) " ) 
69+         
70+         // Log Iterable-specific data if present
71+         if  let  iterableData =  userInfo [ " itbl " ]  as?  [ String :  Any ]  { 
72+             print ( " 🔕 [APP] Iterable-specific data in silent push:  \( iterableData) " ) 
73+             
74+             if  let  isGhostPush =  iterableData [ " isGhostPush " ]  as?  Bool  { 
75+                 print ( " 👻 [APP] Ghost push flag:  \( isGhostPush) " ) 
76+             } 
77+         } 
78+         
79+         // Call completion handler
80+         completionHandler ( . newData) 
81+     } 
82+     
83+     // MARK: - Deep link
84+     
85+     func  application( _ application:  UIApplication ,  continue userActivity:  NSUserActivity ,  restorationHandler:  @escaping  ( [ UIUserActivityRestoring ] ? )  ->  Void )  ->  Bool  { 
86+         return  true  // No deep link handling in this test app
87+     } 
88+     
89+     func  application( _ app:  UIApplication ,  open url:  URL ,  options:  [ UIApplication . OpenURLOptionsKey  :  Any ]  =  [ : ] )  ->  Bool  { 
90+         print ( " 🔗 App opened via direct deep link:  \( url. absoluteString) " ) 
91+         
92+         if  url. scheme ==  " tester "  { 
93+             print ( " ✅ Direct deep link opened - tester:// (will be handled by Iterable SDK) " ) 
94+             return  true 
95+         } 
96+         
97+         return  false 
98+     } 
99+     
100+     // MARK: - Notifications
101+     
102+     func  application( _ applicatiTon:  UIApplication ,  didRegisterForRemoteNotificationsWithDeviceToken deviceToken:  Data )  { 
103+         // Register the device token with Iterable SDK and save it
104+         print ( " Received device token:  \( deviceToken. map  {  String ( format:  " %02.2hhx " ,  $0)  } . joined ( ) ) " ) 
105+         AppDelegate . registerDeviceToken ( deviceToken) 
106+     } 
107+     
108+     func  application( _:  UIApplication ,  didFailToRegisterForRemoteNotificationsWithError _:  Error )  { } 
109+     
110+     // ITBL:
111+     // Setup self as delegate to listen to push notifications.
112+     // Note: This only sets up the delegate, doesn't request permissions automatically
113+     private  func  setupNotifications( )  { 
114+         print ( " 🔔 Setting up notification delegate " ) 
115+         UNUserNotificationCenter . current ( ) . delegate =  self 
116+         print ( " 🔔 Notification delegate set to:  \( String ( describing:  UNUserNotificationCenter . current ( ) . delegate) ) " ) 
117+     } 
118+     
119+     // MARK: - Helper Functions
18120    private  func  setupTestModeUI( )  { 
19121        // Add visual indicator that we're always in integration test mode
20122        DispatchQueue . main. async   { 
@@ -100,92 +202,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
100202        rootViewController. present ( navController,  animated:  true ) 
101203    } 
102204
103-     func  application( _ application:  UIApplication ,  didFinishLaunchingWithOptions launchOptions:  [ UIApplication . LaunchOptionsKey :  Any ] ? )  ->  Bool  { 
104-         // Create window and set root to HomeViewController programmatically for a clean test UI
105-         window =  UIWindow ( frame:  UIScreen . main. bounds) 
106-         let  root  =  UINavigationController ( rootViewController:  HomeViewController ( ) ) 
107-         window? . rootViewController =  root
108-         window? . makeKeyAndVisible ( ) 
109- 
110-         setupNotifications ( ) 
111-         setupTestModeUI ( ) 
112-         
113-         // Start network monitoring
114-         NetworkMonitor . shared. startMonitoring ( ) 
115-         
116-         // Reset device token session state on app launch for clean testing
117-         AppDelegate . resetDeviceTokenSessionState ( ) 
118- 
119-         return  true 
120-     } 
121-     
122-     func  applicationWillResignActive( _:  UIApplication )  { 
123-         // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
124-         // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
125-     } 
126-     
127-     func  applicationDidEnterBackground( _:  UIApplication )  { 
128-         // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
129-         // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
130-     } 
131-     
132-     func  applicationWillEnterForeground( _:  UIApplication )  { 
133-         // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
134-     } 
135-     
136-     func  applicationDidBecomeActive( _ application:  UIApplication )  { 
137-         print ( " 🚀 BREAKPOINT HERE: App became active " ) 
138-         // Set a breakpoint here to confirm app is opening
139-         
140-         // App is always in test mode - no validation needed
141-     } 
142-     
143-     func  applicationWillTerminate( _:  UIApplication )  { 
144-         // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
145-     } 
146-     
147-     // MARK: Silent Push for in-app
148-     
149-     func  application( _ application:  UIApplication ,  didReceiveRemoteNotification userInfo:  [ AnyHashable :  Any ] ,  fetchCompletionHandler completionHandler:  @escaping  ( UIBackgroundFetchResult )  ->  Void )  { 
150-         print ( " 🔕 [APP] Silent push notification received " ) 
151-         print ( " 🔕 [APP] Silent push payload:  \( userInfo) " ) 
152-         
153-         // Log Iterable-specific data if present
154-         if  let  iterableData =  userInfo [ " itbl " ]  as?  [ String :  Any ]  { 
155-             print ( " 🔕 [APP] Iterable-specific data in silent push:  \( iterableData) " ) 
156-             
157-             if  let  isGhostPush =  iterableData [ " isGhostPush " ]  as?  Bool  { 
158-                 print ( " 👻 [APP] Ghost push flag:  \( isGhostPush) " ) 
159-             } 
160-         } 
161-         
162-         // Call completion handler
163-         completionHandler ( . newData) 
164-     } 
165-     
166-     // MARK: Deep link
167-     
168-     func  application( _ application:  UIApplication ,  continue userActivity:  NSUserActivity ,  restorationHandler:  @escaping  ( [ UIUserActivityRestoring ] ? )  ->  Void )  ->  Bool  { 
169-         return  false  // No deep link handling in this test app
170-     } 
171-     
172-     func  application( _ app:  UIApplication ,  open url:  URL ,  options:  [ UIApplication . OpenURLOptionsKey  :  Any ]  =  [ : ] )  ->  Bool  { 
173-         print ( " 🔗 App opened via direct deep link:  \( url. absoluteString) " ) 
174-         
175-         if  url. scheme ==  " tester "  { 
176-             print ( " ✅ Direct deep link opened - tester:// (will be handled by Iterable SDK) " ) 
177-             return  true 
178-         } 
179-         
180-         return  false 
181-     } 
182-     
183-     private  func  showDeepLinkAlert( url:  URL )  { 
205+     private  func  showAlert( with title:  String ,  and message:  String )  { 
184206        guard  let  rootViewController =  window? . rootViewController else  {  return  } 
185207
186208        let  alert  =  UIAlertController ( 
187-             title:  " Iterable Deep Link Opened " ,   
188-             message:  " 🔗 App was opened via Iterable SDK deep link: \n \( url . absoluteString ) " ,   
209+             title:  title , 
210+             message:  message , 
189211            preferredStyle:  . alert
190212        ) 
191213
@@ -201,47 +223,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
201223    } 
202224
203225    private  func  showSilentPushAlert( badgeCount:  Int ,  contentAvailable:  Int  =  0 )  { 
204-         guard  let  rootViewController =  window? . rootViewController else  {  return  } 
205-         
206-         let  alert  =  UIAlertController ( 
207-             title:  " Silent Push Received " ,  
208-             message:  " 🔕 Silent push has been received with a badge count of  \( badgeCount)  and content-available:  \( contentAvailable) " ,  
209-             preferredStyle:  . alert
210-         ) 
211-         
212-         alert. addAction ( UIAlertAction ( title:  " OK " ,  style:  . default) ) 
213-         
214-         // Find the topmost presented view controller
215-         var  topViewController  =  rootViewController
216-         while  let  presentedViewController =  topViewController. presentedViewController { 
217-             topViewController =  presentedViewController
218-         } 
219-         
220-         topViewController. present ( alert,  animated:  true ) 
226+         showAlert ( with:  " Silent Push Received " ,  and:  " 🔕 Silent push has been received with a badge count of  \( badgeCount)  and content-available:  \( contentAvailable) " ) 
221227    } 
222228
223-     // MARK: Notification
224-     
225-     // ITBL:
226-     func  application( _ applicatiTon:  UIApplication ,  didRegisterForRemoteNotificationsWithDeviceToken deviceToken:  Data )  { 
227-         // Register the device token with Iterable SDK and save it
228-         print ( " Received device token:  \( deviceToken. map  {  String ( format:  " %02.2hhx " ,  $0)  } . joined ( ) ) " ) 
229-         AppDelegate . registerDeviceToken ( deviceToken) 
230-     } 
231-     
232-     func  application( _:  UIApplication ,  didFailToRegisterForRemoteNotificationsWithError _:  Error )  { } 
233-     
234-     // ITBL:
235-     // Setup self as delegate to listen to push notifications.
236-     // Note: This only sets up the delegate, doesn't request permissions automatically
237-     private  func  setupNotifications( )  { 
238-         print ( " 🔔 Setting up notification delegate " ) 
239-         UNUserNotificationCenter . current ( ) . delegate =  self 
240-         print ( " 🔔 Notification delegate set to:  \( String ( describing:  UNUserNotificationCenter . current ( ) . delegate) ) " ) 
229+     private  func  showDeepLinkAlert( url:  URL )  { 
230+         showAlert ( with:  " Iterable Deep Link Opened " ,  and:  " 🔗 App was opened via Iterable SDK deep link: \n \( url. absoluteString) " ) 
241231    } 
242232} 
243233
244- // MARK: UNUserNotificationCenterDelegate
234+ // MARK: -  UNUserNotificationCenterDelegate
245235
246236extension  AppDelegate :  UNUserNotificationCenterDelegate  { 
247237    public  func  userNotificationCenter( _ center:  UNUserNotificationCenter ,  willPresent notification:  UNNotification ,  withCompletionHandler completionHandler:  @escaping  ( UNNotificationPresentationOptions )  ->  Void )  { 
@@ -273,11 +263,11 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
273263            } 
274264            // Don't show the system notification UI for silent push
275265
276-             return 
277266            completionHandler ( [ ] ) 
267+             return 
278268        } 
279269
280-         completionHandler ( [ . alert ,  . badge,  . sound] ) 
270+         completionHandler ( [ . banner ,  . badge,  . sound] ) 
281271    } 
282272
283273    // The method will be called on the delegate when the user responded to the notification by opening the application, dismissing the notification or choosing a UNNotificationAction. The delegate must be set before the application returns from applicationDidFinishLaunching:.
@@ -317,7 +307,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
317307    } 
318308} 
319309
320- // MARK: IterableURLDelegate
310+ // MARK: -  IterableURLDelegate
321311
322312extension  AppDelegate :  IterableURLDelegate  { 
323313    // return true if we handled the url
@@ -336,10 +326,14 @@ extension AppDelegate: IterableURLDelegate {
336326            // Check if this is the testview deep link
337327            if  url. host ==  " testview "  { 
338328                print ( " 🎯 Testview deep link detected - showing TestViewController " ) 
339-                 DispatchQueue . main. async   { 
340-                     self . showTestViewController ( ) 
329+                 DispatchQueue . main. asyncAfter ( deadline :   . now ( )   +   3 )  { 
330+                     self . showAlert ( with :   " Deep link to Test View " ,  and :   " Deep link handled with Success! " ) 
341331                } 
342332                return  true 
333+             }  else  if  url. host ==  " iterableurldelegate "  { 
334+                 DispatchQueue . main. async   { 
335+                     self . showAlert ( with:  " IterableURLDelegate called " ,  and:  " Deep link handled with Iterable URL " ) 
336+                 } 
343337            } 
344338
345339            // Show alert for other deep links
@@ -356,50 +350,21 @@ extension AppDelegate: IterableURLDelegate {
356350        print ( " 🔗 URL scheme ' \( url. scheme ??  " nil " ) ' not handled by our app " ) 
357351        return  false  // We didn't handle this URL
358352    } 
359-     
360-     private  func  showTestViewController( )  { 
361-         guard  let  rootViewController =  window? . rootViewController else  { 
362-             print ( " ❌ showTestViewController: no root view controller " ) 
363-             return 
364-         } 
365-         
366-         print ( " 🎯 showTestViewController called - finding topmost view controller " ) 
367-         
368-         let  testVC  =  TestViewController ( ) 
369-         testVC. modalPresentationStyle =  . fullScreen
370-         
371-         // Find the topmost presented view controller
372-         var  topViewController  =  rootViewController
373-         while  let  presentedViewController =  topViewController. presentedViewController { 
374-             topViewController =  presentedViewController
375-         } 
376-         
377-         print ( " 🎯 Found topmost view controller:  \( type ( of:  topViewController) ) " ) 
378-         
379-         // Add a small delay to ensure in-app dismissal animation completes
380-         DispatchQueue . main. asyncAfter ( deadline:  . now( )  +  0.3 )  { 
381-             print ( " 🎯 Presenting TestViewController... " ) 
382-             topViewController. present ( testVC,  animated:  true )  { 
383-                 print ( " ✅ TestViewController presented successfully " ) 
384-             } 
385-         } 
386-     } 
387353} 
388354
389355// MARK: IterableCustomActionDelegate
390356
391357extension  AppDelegate :  IterableCustomActionDelegate  { 
392-     // handle the cutom action from push
358+     
359+     // handle the custom action from push
393360    // return value true/false doesn't matter here, stored for future use
394361    func  handle( iterableCustomAction action:  IterableAction ,  inContext _:  IterableActionContext )  ->  Bool  { 
395-         if  action. type ==  " handleFindCoffee "  { 
396-             if  let  query =  action. userInput { 
397-                 return  false 
398-                 //return //DeepLinkHandler.handle(url: URL(string: "https://example.com/coffee?q=\(query)")!)
362+         if  action. type ==  " showtestsuccess "  { 
363+             DispatchQueue . main. asyncAfter ( deadline:  . now( )  +  3 )  { 
364+                 self . showAlert ( with:  " Custom Action " ,  and:  " Custom Action Handled " ) 
399365            } 
366+             return  true 
400367        } 
401368        return  false 
402369    } 
403-     
404-     // MARK: - Test Network Monitoring
405370} 
0 commit comments