Skip to content

Instantly share code, notes, and snippets.

@JoshHrach
Created January 16, 2024 00:48
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save JoshHrach/8cc3dfbe6409bfaff3b1a20a64506f2c to your computer and use it in GitHub Desktop.
UIViewRepresentable Sample Code
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()
}
}
}
}
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)
}
}
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() { /*...*/ }
}
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