How can I share code between app and widget that contains uiapplication?

OK, so I'm trying to share some utils classes for logging. The problem is a use-case where I want to create a debug notification.

However, inside the app, I want to show a popup instead if the app is showing, but I can't share that code because it uses UIApplication.shared.ApplicationState.

I've tried gating it off with all sorts of methods, @available etc. but I get compilation error "unavailable for application extensions"

Example of me trying:

static func doNotification(_ header: String, message: String) {
//so I'm trying to gate off the code that only can be called in an extension , and in addition I have @available below
    if(isAppExtension()){
        doNotificationFromExtension(header, message: message)
    }else{
        doNotificationFromApp(header, message: message)
    }
}

@available(iOSApplicationExtension, unavailable)
static func doNotificationFromApp(_ header: String, message: String) {
    let state = UIApplication.shared.applicationState
    if state != .active {
        //my dialog handler in-app popup
    }else{
        NotifUtils.createLocalNotification(message, header: header, category: NOTIFICATION_CATEGORY_DEBUG, playSound: false)
    }
}
    
//here I know that I'm in an extension, so app isn't showing - always local notification
static func doNotificationFromExtension(_ header: String, message: String) {
    NotifUtils.createLocalNotification(message, header: header, category: NOTIFICATION_CATEGORY_DEBUG, playSound: false)
}

static func isAppExtension() -> Bool {
    return Bundle.main.executablePath?.contains(".appex/") ?? false
}

Is there any way to share the code like this? The reason I want to do this is because I have various live activity code that I'd want to re-use, but this is a show.-stopper.

App Groups will work across UIFrameworks (SwiftUI, UIKit). There is also an example of this in Emoji Rangers.

As for sharing code, UIApplication is not available to App Extensions so you'd need to use a shared location so either side can know of updates. The only pseudo real time way to listen and receive updates would be to use Unix sockets, but isn't a good ideal for Widgets because they don't have lifecycle.

Rico WWDR - DTS - Software Engineer

I am not entirely certain of your use case, but based on what you've described it seems like a good case for making a protocol and having two conforming classes / structs, one for the app, and another that lives in the extension. When the protocol's methods are called, they are delegated to the proper one.

Another way to do it is to have a protocol and create two extensions:

protocol NotificationDelegate { 
    func doNotification()
}

The first extension lives in a file that has target membership of your main application or framework:

extension MyLoggingClass: NotificationDelegate {
    func doNotification(...) {
       // will only be called by app, can use UIApplication here
    }
}

Then put this one in your extension:

extension MyLoggingClass: NotificationDelegate {
    func doNotification(...) {
       // will only be called by app extension
    }
}

Hey thanks for great responses! I am currently looking at extensions.

this way, I can have the MyLoggingClass contain the code that works everywhere, and then in an extension to MyLoggingClass, that I put inside the App only, I override the "doNotification"method to contain the logic to see if the app is running.

This way, in the extension the "regular" method will be called, and in the app the overridden method will be called.

This would work right?

How can I share code between app and widget that contains uiapplication?
 
 
Q