SwiftUI 2 lifecycle - handle custom URL scheme - ios

Until now we were able to handle custom URL schemes that launch the app using AppDelegate or SceneDelegate. But how is this possible using the new lifecycle?
I tried adding an #UIApplicationDelegateAdaptor with the application:openURL:options: function but that is never called. The closest I've got is using the Environment's scenePhase but that only tells the state of the scene (active, background etc.), not the incoming URL.

You can use the onOpenURL(perform:) modifier either in the body of you App or Scene or on views in your hierachy. The modifier gets called multiple times as well, so you could set the state for each view individually. With that your AppDelegate no longer needs to know your whole navigagion, which is great.

Related

Trigger onOpenUrl with specific url programmatically within SwiftUI App

Circumstances
I've got a SwiftUI App with deep link support. When .onOpenUrl is triggered, the app navigates to a specific screen. Every view can listen to that deep link url and therefore has all information to properly set the relevant states (like the TabView selecting a specific tab).
I use deep links for Widgets.
Now that my app supports push notifications, I want to use that deep link navigation handling to open a specific screen based on the push notifications userInfo that comes from the according UIApplicationDelegate method.
Idea
The idea is to generate a deep link url from that user info and pass it down the view hierarchy so that every view can react to .onOpenUrl and set state based on the opened push notification. That way I don't have to add an extra EnvironmentObject to the environment and listen to .onChange(of: someUserInfoInsideTheEnvironment) in every view, duplicating the existing .onOpenUrl handling for deep links.
Question
Is there a way to manually (programmatically) trigger .onOpenUrl with a specific url?
Like setting a specific environment value or -object so that every view in the view hierarchy will call .onOpenUrl with my own deep link url?

Is SceneDelegate mandatory? [duplicate]

This question already has answers here:
Opt out of UISceneDelegate/SwiftUI on iOS
(6 answers)
Closed 3 months ago.
The question says it all.
There's the following line in apple documentation,
Scenes are opt in, but you must support them if you want to display
multiple copies of your app’s UI simultaneously.
It's not mentioned whether the SceneDelegate is mandatory or optional or a recommendation (I'm aware that the SceneDelgate is used to handle the lifecycle of the scene).
In a iOS 13+ device, can I create an app without SceneDelegate?
I defined the UIWindow variable in the AppDelgate and set the ViewController in application(didFinishLaunchingWithOptions), like before iOS 13. But that doesn't work and displays a blank screen.
And thus, this question. Is Scenedelgate mandatory even if we don't opt for multiple scenes?
Here's my observation:
Multiple scenes are optional. But you still have to support at least
one scene... and for that, SceneDelegate is mandatory.
If I'm wrong and SceneDelegate is optional (like described in this stackoverflow post), please help with the flows.
In a iOS 13+ device, can I create an app without SceneDelegate?
Yes. All apps do have scenes, but if you go with the app-delegate-only architecture, a single UIWindowScene will be created behind the scenes (pun intended). The app will run perfectly well on both iPhone and iPad, with all the usual lifetime events arriving as usual into the app delegate (though I do not know what will happen on Apple Silicon).
I defined the UIWindow variable in the AppDelgate and set the ViewController in application(didFinishLaunchingWithOptions), like before iOS 13. But that doesn't work and displays a blank screen.
This is because you did not correctly convert from the scene delegate architecture, which is provided by the app template you started with, to an app delegate architecture. Basically, you've left pieces of the scene delegate architecture lying around. Perhaps you did not delete all references to the scene delegate; perhaps you forgot to delete the UIApplicationSceneManifest entry from the Info.plist. Whatever the reason, the result is that the runtime thinks this app still uses scene delegate architecture, and it then fails to find certain pieces that it's looking for and shows the blank screen.
So, just to sum up what to do when you've started with the built-in app template:
Delete the SceneDelegate.swift file.
In the App Delegate, delete the two UISceneSession methods.
In the App Delegate, add a window reference as an instance property: var window: UIWindow?
In the Info.plist, completely delete the entire UIApplicationSceneManifest entry (and save).
Profit.

Can't understand what UIScenes are

I can't find a clear definition of what UIScenes are
Are they just for handling the background calls? Are they like a ViewController? Do we use them often or nah?
The biggest thing is that scenes set up multiple window support. It is also useful for SwiftUI.
The SceneDelegate controls what is displayed on the screen "to manage life-cycle events in one instance of your app's user interface.", while the AppDelegate controls your entire app life-cycle.
Read the App and Environment Article and scenes from Apple instead of UIScene documentation.
Scene:
Scene, Manage multiple instances of your app’s UI simultaneously, and
direct resources to the appropriate instance of your UI.
We had only one scene back then before iOS 13, So the only thing we need to run ViewControllers simultaneously was multiple Windows on top of each other. But now, each application can have multiple instances running at the same time! Each scene has its own state and it might be in the foreground while others are in the background or are suspended, while Window was completely dependent on the application itself.
Imagine we have 2 view controllers (consider there are no scenes) running on the left and right side of the device and then we need to show a banner. Using the old window method will show the banner on both of them! And if you need to pick one, you may end up finding the correct controller and presenting the banner on it.
So apple introduced Scene, a container for each separate instance of the app. So you can manage each one separately and each of them acts as a separate app. It has its own windows and controllers. But all of them are managed by a single object, UIApplication.shared and it has a delegate to handle general events (usually from outside of the app) and entire application life cycle.

Should my app be updated to Scene Delegate

Should my app be updated to Scene Delegate from App Delegate. My app supports ios 13.0 and up
first you have to understand what is difference
You could think of them as the global and private versions. One is shared and the other is limited to the individual owner. In a way, they are exactly what you would expect by the names.
Multi-window support is happening
Next time you create a new Xcode project you’ll see your AppDelegate has split in two: AppDelegate.swift and SceneDelegate.swift. This is a result of the new multi-window support that landed with iPadOS, and effectively splits the work of the app delegate in two.
From iOS 13 onwards, your app delegate should:
Set up any data that you need for the duration of the app.
Respond to any events that focus on the app, such as a file being shared with you.
Register for external services, such as push notifications.
Configure your initial scenes.
In contrast, scene delegates are there to handle one instance of your app’s user interface. So, if the user has created two windows showing your app, you have two scenes, both backed by the same app delegate.
Keep in mind that these scenes are designed to work independently from each other. So, your application no longer moves to the background, but instead individual scenes do – the user might move one to the background while keeping another open.
at last I will say that you can go with Scene Delegate
Courtesy of https://www.hackingwithswift.com/articles/193/whats-new-in-ios-13

Custom iOS popup/modal view jailbreak launch daemon

I'm working on a jailbreak tweak (launch daemon) that simply listens for a certain event then will need to display a custom popup UIView when that event occurs. The popup needs to appear wherever - so either lockscreen, springboard or in app.
Whilst I have managed to get a simple CFUserNotificationDisplayAlert working, it does not offer the required functionality - I would prefer a custom view to be rendered.
I have tried using the RNBlurModalView library here, but this crashes when attempting to render the view as it looks for a base UIViewController - there isn't one as it's a background daemon.
Does anyone have any tips how I can go about rendering a custom popup view (whether it's modifying the above RNBlur library or rolling a different solution)?
Thanks! :)
What you can do is inject a dynamic library into SpringBoard in which you use the CPDistributedMessagingCenter class in server mode and you set it up in a way so that it listens for a message, then upon receiving that message, its observer object renders the custom view and adds it to the key window of the SpringBoard application itself ([[UIApplication sharedApplication].keyWindow addSubview:customView];).
Then, in the other part of the tweak (where you're currently calling CFUserNotificationDisplayAlert()), you simply use CPDistributedMessagingCenter in client mode and send it the appropriate message whenever needed.

Resources