I have a class that makes a network call. I want to be able to use this class in both the main app and App Extension. However, in this class I use: UIApplication.shared.isNetworkActivityIndicatorVisible
.
Since shared
isn't available in App Extensions, is there a way that I can use something along the lines of #available
such that I don't have to duplicate this class just because of that one line of code? (I could just remove the activity indicator but I rather not since I like to let users know when network calls are happening)
I've tried adding a pre-compiled Macro as suggested by an answer I found on another question, but the compile still complains.
Use dependency injection pattern to refactor out the code depending on UIApplication.shared
.
Use a protocol to describe the functionality that is currently provided by UIApplication.shared
.
Implement that protocol for the base app, where UIApplication.shared
is available and use it there. Implement another implementation without using UIApplication.shared
, which would be used for app extensions.
Refactor your current class to use the protocol implementing objects and inject the proper implementation at the initialization (dependency injection pattern) - initializer of that class would accept a protocol implementation.
Wire up a proper implementation when creating an instance of the refactored class - in app extension pass it the implementation without UIApplication.shared
, in base app the one with UIApplication.shared
.
So e.g., Let's have this big class here:
class Big {
... a lot of code ...
func a() {
... again some code ...
// here the code that needs shared
UIApplication.shared.isNetworkActivityIndicatorVisible = true
... more code ...
}
}
So first, a protocol:
protocol NetworkIndicator {
func showActivity()
}
Then two implementations:
class AppNetworkIndicator: NetworkIndicator {
func showActivity() {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
}
class ExtensionNetworkIndicator: NetworkIndicator {
func showActivity() {}
}
Refactor Big
to support dependency injection:
class Big {
private let networkIndicator: NetworkIndicator
init(networkIndicator: NetworkIndicator) {
self.networkIndicator = networkIndicator
}
... rest of code ...
func a() {
... again some code ...
// use injected protocol implementation
networkIndicator.showActivity()
... more code ...
}
}
Finally, in the app, where you use the Big
class, initiate it with:
let big = Big(networkIndicator: AppNetworkIndicator())
And in the extension, use the other implementation:
let big = Big(networkIndicator: ExtensionNetworkIndicator())