Post

Replies

Boosts

Views

Activity

Universal link not passed to SceneDelegate when app runs in the background
I have a SwiftUI app which supports a launch from a configured universal link. I'm following this documentation. When the app is not running and I tap a universal link, app launches. This proves the association of the website and the app. Now, when the app is already running in the background, and then I tap a universal link, things don't work as expected. Quoting from the documentation If your app has opted into Scenes, and your app is not running, the system delivers the universal link to the scene(:willConnectTo:options:) delegate method after launch, and to scene(:continue:) when the universal link is tapped while your app is running or suspended in memory. I've implemented scene(_:continue:) in my SceneDelegate but it never gets invoked. I'm pasting some relevant logs AppDelegate.application(_:willFinishLaunchingWithOptions:) AppDelegate.application(_:didFinishLaunchingWithOptions:) AppDelegate.application(_:configurationForConnecting:options:) SceneDelegate.scene(_:willConnectTo:options:) SceneDelegate.sceneWillEnterForeground(_:) NSNotificationName(_rawValue: UIApplicationWillEnterForegroundNotification) SceneDelegate.sceneDidBecomeActive(_:) NSNotificationName(_rawValue: UIApplicationDidBecomeActiveNotification) Now, I background the app... SceneDelegate.sceneWillResignActive(_:) NSNotificationName(_rawValue: UIApplicationWillResignActiveNotification) SceneDelegate.sceneDidEnterBackground(_:) NSNotificationName(_rawValue: UIApplicationDidEnterBackgroundNotification) App runs in the background... Now, I tap a Universal link SceneDelegate.sceneWillEnterForeground(_:) NSNotificationName(_rawValue: UIApplicationWillEnterForegroundNotification) SceneDelegate.sceneDidBecomeActive(_:) NSNotificationName(_rawValue: UIApplicationDidBecomeActiveNotification) As shown in the logs above, there is no trace of scene(_:continue:). func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { Log("SceneDelegate.scene(_:continue:)") guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let universalLink = userActivity.webpageURL else { Log("Not launched via universal links!") return } Log(String(format: "userActivities = %@", String(describing: userActivity))) Log(String(format: "universalLink = %@", universalLink.absoluteString)) StaticContext.dataFromMainApp = universalLink.absoluteString StaticContext.viewController.updateLabelWithLink() } What am I missing here?
1
1
2.0k
Feb ’24
IOS warning: instance method 'userNotificationCenter(_:willPresent:withCompletionHandler:)' nearly matches optional requirement
In an iOS project, I have implemented the following delegate method to handle Notifications when app is in foregorund: func userNotificationCenter (_ pNotificationCenter : UNUserNotificationCenter, willPresent pNotification : UNNotification, withCompletionHandler pCompletionHandler : @escaping (UNNotificationPresentationOptions) -> Void) -> Void { // When app is in foreground, notification is directly sent to // the app by invoking this delegate method. } When building, I'm getting the warning. But my implementation is correct according to documentation. Why is this method not recognized as the implementation of the UNUserNotificationCenterDelegate protocol? This is the warning in text format: Showing All Issues <file path & line number>: Instance method 'userNotificationCenter(_:willPresent:withCompletionHandler:)' nearly matches optional requirement 'userNotificationCenter(_:willPresent:withCompletionHandler:)' of protocol 'UNUserNotificationCenterDelegate' This is the image of the warning: Am I missing some flag in a compiler setting? My env: Xcode 15.2, Swift 5.0, Deployment target - iOS 14.0+.
3
1
970
Feb ’24
Notification Service Extension restrictions
I have an iOS app which uses Notification Service Extension (NSE) to process incoming notifications before it displayed to user. In NSE, as part of initialization of my app, I need to iterate through a 2D array. There are roughly 65k iterations. I've noticed that this iteration fails somewhere in between and the NSE process crashes... I can say it crashes because the logs stopped in between the iterations. This results in 'unmodified notification' getting displayed immediately, whereas NSE is granted 30 sec of background execution. My question is, why does this happen? The above iteration of 2D array works in app, but fails in NSE. Is there some kind of restriction on background extensions? - the documentation only talks about a time limit of 30sec. If there is some kind of restriction (like CPU and memory), how does one know this and code for it... since Apple did not provide any documentation. Or perhaps, there is a completely different reason?
3
1
1.2k
Jun ’24
Moving SceneDelegate to a different target
I have a SwiftUI project which has the following hierarchy: IOSSceneDelegate (App target) - depends on EntryPoint and Presentation static libs. Presentation (Static library) - Depends on EntryPoint static lib. Contains UI related logic and updates the UI after querying the data layer. EntryPoint (Static library) - Contains the entry point, AppDelegate (for its lifecycle aspects) etc. I've only listed the relevant targets here. SceneDelegate was initially present in EntryPoint library, because the AppDelegate references it when a scene is created. public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -&gt; UISceneConfiguration { // Set the SceneDelegate dynamically let sceneConfig: UISceneConfiguration = UISceneConfiguration(name: "mainWindow", sessionRole: connectingSceneSession.role) sceneConfig.delegateClass = SceneDelegate.self return sceneConfig } The intent is to move the SceneDelegate to the Presentation library. When moved, the EntryPoint library fails to compile because it's referencing the SceneDelegate (as shown above). To remove this reference, I tried to set up the SceneDelegate in the old way - In the info.plist file, mention a SceneConfiguration and set the SceneDelegate in Presentation. // In the Info.plist file &lt;key&gt;UIApplicationSceneManifest&lt;/key&gt; &lt;dict&gt; &lt;key&gt;UIApplicationSupportsMultipleScenes&lt;/key&gt; &lt;true/&gt; &lt;key&gt;UISceneConfigurations&lt;/key&gt; &lt;dict&gt; &lt;key&gt;UIWindowSceneSessionRoleApplication&lt;/key&gt; &lt;array&gt; &lt;dict&gt; &lt;key&gt;UISceneConfigurationName&lt;/key&gt; &lt;string&gt;Default Configuration&lt;/string&gt; &lt;key&gt;UISceneDelegateClassName&lt;/key&gt; &lt;string&gt;Presentation.SceneDelegate&lt;/string&gt; &lt;/dict&gt; &lt;/array&gt; &lt;/dict&gt; &lt;/dict&gt; // In the AppDelegate public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -&gt; UISceneConfiguration { // Refer to a static UISceneconfiguration listed in the info.plist file return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } As shown above, the Presentation.SceneDelegate is referred in the Info.plist file and the reference is removed from the AppDelegate (in EntryPoint library). The app target compiles, but when I run it, the SceneDelegate is not invoked. None of the methods from the SceneDelegate (scene(_:willConnectTo:options:), sceneDidDisconnect(_:), sceneDidEnterBackground(_:) etc.) are invoked. I only get the AppDelegate logs. It seems like the Configuration is ignored because it was incorrect. Any thoughts? Is it possible to move the SceneDelegate in this situation?
0
1
400
Feb ’25
SwiftUI Vs AppKit for a complex and dynamic UI
I'm looking to develop a very rich networking macOS app (like social media apps) operated by very large number of users, each user is able to create a number of windows, operate/view each of them, able to customize the app to his liking etc. The UI is expected to be very rich and dynamic. The question is, should I choose AppKit or SwiftUI? I have a basic understanding of SwiftUI, its declarative way of defining UI layouts and populating it with data. Not sure if SwiftUI can handle a very rich and dynamic UI customised by large number of users. Any thoughts? What works best in this scenario? What is Apple's recommendation?
1
1
445
Feb ’25
Periodic iOS background execution
An app has some periodic light background work, which is expected to run even when app is suspended. Ofc, if user has swiped up, nothing can be done. When swiped from app switcher, if app was in Suspended state, its not informed else, in every other state (including background), applicationWillTerminate(_:) is invoked When application is not killed by user and is in suspended state, I want to run some small tasks at certain intervals. According to this documentation, Background fetch is the way to go. This post by Apple DTS also suggests the same i.e., Background Fetch (BGAppRefreshTask) for periodic background execution. Example: The sample background task is to count 10s in multiple of 10s. Launch handler is registered with the background task ID configured in info.plist file in application(_:didFinishLauchingWithOptions:). I have the following code invoked from in applicationDidEnterBackground(_:), func initiateBackgroundTask(id: String) {         let currentDate: Date = Date.now         guard let futureDate: Date = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate) else {             NSLog(AppDelegate.TAG + "Error in obtaining future date!")             return         }         let taskRequest: BGAppRefreshTaskRequest = BGAppRefreshTaskRequest(identifier: id)         // Schedule background task         taskRequest.earliestBeginDate = futureDate         do {             // Note: Background processing doesn't work in Simulator.             // Submitting in Simulator leads to BGTaskScheduler.Error.Code.unavailable error.             try BGTaskScheduler.shared.submit(taskRequest)             NSLog(AppDelegate.TAG + "Task submitted successfully!")         } catch {             NSLog(AppDelegate.TAG + "error = " + String(describing: error))             return         }         NSLog(AppDelegate.TAG + "Background task scheduled successfully!!")         NSLog(AppDelegate.TAG + "Scheduled date = %@ | Present date = %@", String(describing: taskRequest.earliestBeginDate), String(describing: Date.now))     } The following method is invoked from launch handler: func taskRefreshCount1Min(task: BGAppRefreshTask) {              // Set expiration handler         task.expirationHandler = {            NSLog(AppDelegate.TAG + "Background execution time about to expire!")            NSLog(AppDelegate.TAG + "Remaining time = %fsec | %@", AppDelegate.app.backgroundTimeRemaining, String(describing: Date.now))             NSLog(AppDelegate.TAG + "Unable to complete task!!")             task.setTaskCompleted(success: false)         }         for i in 1...6 {             let presentDate: Date = Date.now             NSLog(AppDelegate.TAG + "%d) %@", i, String(describing: presentDate))             Thread.sleep(forTimeInterval: 10)         }         NSLog(AppDelegate.TAG + "Task complete!")         task.setTaskCompleted(success: true)     } My expectation is that iOS will execute the launch handler 1 min after scheduling the background task. But that never happens, even after hours. Task did get executed within 20 mins (Sample output shown below), but every other time, I waited for more than an hour and task was never executed. // Output ... Task submitted successfully! Background task scheduled successfully!! Scheduled date = Optional(2023-02-06 09:19:46 +0000) | Present date = 2023-02-06 09:18:46 +0000 TaskRefreshCount1Min(task:) 1) 2023-02-06 09:35:12 +0000 2) 2023-02-06 09:35:22 +0000 3) 2023-02-06 09:35:32 +0000 The documentation does state, However, the system doesn’t guarantee launching the task at the specified date, but only that it won’t begin sooner. But I didn't expect the results to differ by such a huge margin. Apparently others have also faced this 'inconsistent scheduling' in iOS. Background fetch with BGTaskScheduler works perfectly with debug simulations but never works in practice How make iOS app running on background Every one minute in Swift? In links I have pasted above, despite Background Fetch being the most suitable for periodic light tasks, Silent Push Notifications were suggested. I'm currently checking out Silent Push Notifications, but iOS recommends a frequency of not more than 3 per hour. Summarising my questions from this exercise: Is there something wrong with the code? What technique should I use? Background fetch, silent notifications or anything else? In Background Fetch, how do you schedule background tasks periodically? There's an instance property called earliestBeginDate to denote the minimum time after which the task can happen.
2
3
3.2k
Feb ’23