Skip to content

Instantly share code, notes, and snippets.

@overlair
Created October 28, 2023 03:26
Show Gist options
  • Save overlair/2cfb7f29a5917799920d22c28c40b7f5 to your computer and use it in GitHub Desktop.
Save overlair/2cfb7f29a5917799920d22c28c40b7f5 to your computer and use it in GitHub Desktop.
UIKit Gestures in SwiftUI
import SwiftUI
struct ExampleUIKitGestureViewA: View {
var body: some View {
Color.blue
.overlay { ExampleUIKitGestureViewRepresentableA() }
/*
can also place it behind if hits are disabled on attaching view,
or you have other views you want to receive gestures that it would block
.background { ExampleUIKitGestureViewRepresentable() }
*/
}
}
struct ExampleUIKitGestureViewRepresentableA: UIViewRepresentable {
func makeUIView(context: Context) -> some UIView {
let v = UIView()
/*
declare necessary gestures here, and attach them to callbacks in a "Coordinator", or delegate object that implements recognizer functions, or other delegate functions for interactions (like UIDragInteraction)
*/
let tap = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.tap))
v.addGestureRecognizer(tap)
return v
}
func updateUIView(_ uiView: UIViewType, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator: NSObject, UIGestureRecognizerDelegate {
@objc func tap(gesture: UITapGestureRecognizer) {
// do something with tap here
}
}
}
/*
If you'd rather handle the gesture callbacks in a SwiftUI view, you can use a callback function and simply pass along the gesture parameters
*/
struct ExampleUIKitGestureViewB: View {
var body: some View {
Color.blue
.overlay { ExampleUIKitGestureViewRepresentableB(event: handle) }
}
func handle(_ event: ExampleUIKitGestureEvent) {
// handle gesture callback in SwiftUI view
}
}
enum ExampleUIKitGestureEvent {
case tap(UITapGestureRecognizer)
}
struct ExampleUIKitGestureViewRepresentableB: UIViewRepresentable {
let event: (ExampleUIKitGestureEvent) -> ()
func makeUIView(context: Context) -> some UIView {
let v = UIView()
let tap = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.tap))
v.addGestureRecognizer(tap)
return v
}
func updateUIView(_ uiView: UIViewType, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator(event: event)
}
class Coordinator: NSObject, UIGestureRecognizerDelegate {
let event: (ExampleUIKitGestureEvent) -> ()
init(event: @escaping (ExampleUIKitGestureEvent) -> Void) {
self.event = event
}
@objc func tap(gesture: UITapGestureRecognizer) {
event(.tap(gesture))
}
}
}
/*
For handling raw touches, you'll need to define your own custom UIView
*/
class TouchHandlingUIView: UIView {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// do something with touches
}
}
/*
can use this in place of a standard UIView
func makeUIView(context: Context) -> some UIView {
let v = TouchHandlingUIView()
return v
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment