我将保罗的回答与苹果公司过时的例子结合起来,创造了一种检测任意数量的触摸的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import Foundation
import UIKit

class NFingerGestureRecognizer: UIGestureRecognizer {

var tappedCallback: (UITouch, CGPoint?) -> Void

var touchViews = [UITouch:CGPoint]()

init(target: Any?, tappedCallback: @escaping (UITouch, CGPoint?) -> ()) {
self.tappedCallback = tappedCallback
super.init(target: target, action: nil)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
for touch in touches {
let location = touch.location(in: touch.view)
// print("Start: (\(location.x)/\(location.y))")
touchViews[touch] = location
tappedCallback(touch, location)
}
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
for touch in touches {
let newLocation = touch.location(in: touch.view)
// let oldLocation = touchViews[touch]!
// print("Move: (\(oldLocation.x)/\(oldLocation.y)) -> (\(newLocation.x)/\(newLocation.y))")
touchViews[touch] = newLocation
tappedCallback(touch, newLocation)
}
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
for touch in touches {
// let oldLocation = touchViews[touch]!
// print("End: (\(oldLocation.x)/\(oldLocation.y))")
touchViews.removeValue(forKey: touch)
tappedCallback(touch, nil)
}
}

}

你需要把它包装,把它作为一个 SwiftUI 组件使用:UIViewRepresentable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import Foundation
import SwiftUI

struct TapView: UIViewRepresentable {

var tappedCallback: (UITouch, CGPoint?) -> Void

func makeUIView(context: UIViewRepresentableContext<TapView>) -> TapView.UIViewType {
let v = UIView(frame: .zero)
let gesture = NFingerGestureRecognizer(target: context.coordinator, tappedCallback: tappedCallback)
v.addGestureRecognizer(gesture)
return v
}

func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<TapView>) {
// empty
}

}

如何在 SwiftUI 中使用的小例子:TapView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var body: some View {
guard let img = UIImage(named: "background.png") else {
fatalError("Unable to load image")
}
return GeometryReader { geometry in
ZStack {
Image(uiImage: img)
.resizable()
.aspectRatio(geometry.size, contentMode: .fill)
.edgesIgnoringSafeArea(.all)


TapView { touch, optLocation in
// touch can be used as a dictionary key.
// optLocation is nil when the touch ends.
}
}
}
}

原文地址

stackoverflow.com