Skip to content

Instantly share code, notes, and snippets.

@arthurschiller
Last active March 6, 2024 14:17
Show Gist options
  • Save arthurschiller/a4471129584d11e9b358d99bad4aa0dc to your computer and use it in GitHub Desktop.
Save arthurschiller/a4471129584d11e9b358d99bad4aa0dc to your computer and use it in GitHub Desktop.
InjectionIII Utils and Helper
#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