Created
January 16, 2024 00:48
-
-
Save JoshHrach/8cc3dfbe6409bfaff3b1a20a64506f2c to your computer and use it in GitHub Desktop.
UIViewRepresentable Sample Code
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
struct ThirdPartyDemoView: View { | |
@State private var shouldAdd = true | |
@State private var currentValue = 0 | |
var body: some View { | |
ThirdPartyReader { proxy in | |
Text("\(currentValue)") | |
ThirdPartyView(shouldAdd: shouldAdd) | |
.viewChangedValueTo { view, newValue in | |
currentValue = newValue | |
} | |
Toggle("Add?", isOn: $shouldAdd) | |
Button("Perform Action") { | |
proxy.changeInternalValue() | |
} | |
} | |
} | |
} |
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
class ThirdPartyProxy: ObservableObject { | |
fileprivate var view: ThirdPartyUIView? | |
func changeInternalValue() { | |
view?.changeInternalValue() | |
} | |
} | |
extension EnvironmentValues { | |
private struct ThirdPartyProxyEnvironmentKey: EnvironmentKey { | |
static var defaultValue: ThirdPartyProxy? = nil | |
} | |
var thirdPartyProxy: ThirdPartyProxy? { | |
get { self[ThirdPartyProxyEnvironmentKey.self] } | |
set { self[ThirdPartyProxyEnvironmentKey.self] = newValue } | |
} | |
} | |
struct ThirdPartyReader<Content: View>: View { | |
@StateObject private var proxy = ThirdPartyProxy() | |
private var content: (ThirdPartyProxy) -> Content | |
init(@ViewBuilder _ content: @escaping (ThirdPartyProxy) -> Content) { | |
self.content = content | |
} | |
var body: some View { | |
content(proxy) | |
.environment(\.thirdPartyProxy, proxy) | |
} | |
} |
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
protocol ThirdPartyViewDelegate { | |
func view(_ view: ThirdPartyUIView, changedValueTo newValue: Int) | |
} | |
class ThirdPartyUIView: UIView { | |
var shouldAdd: Bool = true | |
var delegate: ThirdPartyViewDelegate? | |
// Same as button tap in view. Results reported via delegate | |
func changeInternalValue() { /*...*/ } | |
} |
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
struct ThirdPartyViewRepresentable: UIViewRepresentable { | |
@State private var actionTriggered = false | |
var delegate: ThirdPartyViewDelegate? = nil | |
var proxy: ThirdPartyProxy? | |
var shouldAdd: Bool | |
func makeUIView(context: Context) -> ThirdPartyUIView { | |
let view = ThirdPartyUIView() | |
view.shouldAdd = shouldAdd | |
view.delegate = delegate | |
proxy?.view = view | |
return view | |
} | |
func updateUIView(_ uiView: ThirdPartyUIView, context: Context) { | |
uiView.shouldAdd = shouldAdd | |
} | |
} | |
struct ThirdPartyView: View { | |
@Environment(\.thirdPartyProxy) private var proxy | |
var shouldAdd: Bool | |
@State private var coordinator = ThirdPartyCoordinator() | |
var body: some View { | |
ThirdPartyViewRepresentable(delegate: coordinator, proxy: proxy, shouldAdd: shouldAdd) | |
} | |
} | |
extension ThirdPartyView { | |
class ThirdPartyCoordinator: ThirdPartyViewDelegate { | |
var viewChangedValueTo: ((ThirdPartyUIView, Int) -> Void)? | |
var externalDelegate: ThirdPartyViewDelegate? | |
func view(_ view: ThirdPartyUIView, changedValueTo newValue: Int) { | |
viewChangedValueTo?(view, newValue) | |
externalDelegate?.view(view, changedValueTo: newValue) | |
} | |
} | |
func setViewDelegate(_ delegate: ThirdPartyViewDelegate) -> Self { | |
coordinator.externalDelegate = delegate | |
return self | |
} | |
func viewChangedValueTo(_ closure: @escaping (_ view: ThirdPartyUIView, _ newValue: Int) -> Void) -> Self { | |
coordinator.viewChangedValueTo = closure | |
return self | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment