Last active
March 6, 2024 14:17
-
-
Save arthurschiller/a4471129584d11e9b358d99bad4aa0dc to your computer and use it in GitHub Desktop.
InjectionIII Utils and Helper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if DEBUG | |
import Combine | |
private var loadInjectionOnce: () = { | |
guard objc_getClass("InjectionClient") == nil else { | |
return | |
} | |
#if targetEnvironment(simulator) | |
// Running on Simulator | |
let bundleName: String | |
#if os(macOS) || targetEnvironment(macCatalyst) | |
bundleName = "macOSInjection.bundle" | |
#elseif os(visionOS) | |
bundleName = "xrOSInjection.bundle" | |
#else | |
bundleName = "iOSInjection.bundle" | |
#endif | |
let bundlePath = "/Applications/InjectionIII.app/Contents/Resources/"+bundleName | |
guard | |
let bundle = Bundle(path: bundlePath), bundle.load() | |
else { | |
fatalError(""" | |
⚠️ Could not load injection bundle from \(bundlePath). \ | |
Have you downloaded the InjectionIII.app from either \ | |
https://github.com/johnno1962/InjectionIII/releases \ | |
or the Mac App Store? | |
""") | |
} | |
#else | |
// Running on Real Device | |
let resourceName: String | |
#if os(macOS) || targetEnvironment(macCatalyst) | |
resourceName = "macOSInjection" | |
#elseif os(visionOS) | |
resourceName = "iOSInjection" // seems to work without using xrOSInjection | |
#else | |
resourceName = "iOSInjection" | |
#endif | |
guard | |
let bundlePath = Bundle.main.path(forResource: resourceName, ofType: "bundle"), | |
let bundle = Bundle(path: bundlePath), bundle.load() | |
else { | |
fatalError(""" | |
⚠️ Could not load injection bundle for \(resourceName). \ | |
Did you add the corresponding Run Script Phase? -> | |
""") | |
} | |
#endif | |
}() | |
public let injectionObserver = InjectionObserver() | |
public class InjectionObserver: ObservableObject { | |
@Published var injectionNumber = 0 | |
var cancellable: AnyCancellable? = nil | |
let publisher = PassthroughSubject<Void, Never>() | |
init() { | |
cancellable = NotificationCenter.default.publisher(for: | |
Notification.Name("INJECTION_BUNDLE_NOTIFICATION")) | |
.sink { [weak self] change in | |
self?.injectionNumber += 1 | |
self?.publisher.send() | |
} | |
} | |
} | |
extension SwiftUI.View { | |
public func eraseToAnyView() -> some SwiftUI.View { | |
_ = loadInjectionOnce | |
return AnyView(self) | |
} | |
public func enableInjection() -> some SwiftUI.View { | |
return eraseToAnyView() | |
} | |
public func loadInjection() -> some SwiftUI.View { | |
return eraseToAnyView() | |
} | |
public func onInjection(bumpState: @escaping () -> ()) -> some SwiftUI.View { | |
return self | |
.onReceive(injectionObserver.publisher, perform: bumpState) | |
.eraseToAnyView() | |
} | |
} | |
@available(iOS 13.0, *) | |
@propertyWrapper | |
public struct ObserveInjection: DynamicProperty { | |
@ObservedObject private var iO = injectionObserver | |
public init() {} | |
public private(set) var wrappedValue: Int { | |
get {0} set {} | |
} | |
} | |
#else | |
extension SwiftUI.View { | |
@inline(__always) | |
public func eraseToAnyView() -> some SwiftUI.View { return self } | |
@inline(__always) | |
public func enableInjection() -> some SwiftUI.View { return self } | |
@inline(__always) | |
public func loadInjection() -> some SwiftUI.View { return self } | |
@inline(__always) | |
public func onInjection(bumpState: @escaping () -> ()) -> some SwiftUI.View { | |
return self | |
} | |
} | |
@available(iOS 13.0, *) | |
@propertyWrapper | |
public struct ObserveInjection { | |
public init() {} | |
public private(set) var wrappedValue: Int { | |
get {0} set {} | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment