import SwiftUI
struct Level1: View {
@State var tapScore = 0
@State var showingMinedHammer = false
@State var points:[CGPoint] = [CGPoint(x:0,y:0), CGPoint(x:50,y:50)]
@State private var location = CGPoint.zero // < here !!
func mine() {
tapScore = 1
showMinedHammer()
}
func showMinedHammer() {
self.showingMinedHammer = true
DispatchQueue.main.asyncAfter(deadline: .now() 99) {
self.showingMinedHammer = false
}
}
var body: some View {
GeometryReader { geometryProxy in
ZStack {
Image("hammer.fill").resizable().frame(width: UIScreen.main.bounds.height * 1.4, height: UIScreen.main.bounds.height)
.gesture(DragGesture(minimumDistance: 0).onEnded { value in
self.location = value.location // < here !!
self.mine()
})
if self.showingMinedHammer {
Image(systemName: "hammer.fill")
.resizable()
.frame(width: 30, height: 30)
.position(self.location) // < here !!
}
}
}.edgesIgnoringSafeArea(.all)
}
}
struct Level1_Previews: PreviewProvider {
static var previews: some View {
Level1()
}
}
struct GetTapLocation:UIViewRepresentable {
var tappedCallback: ((CGPoint) -> Void)
func makeUIView(context: UIViewRepresentableContext<GetTapLocation>) -> UIView {
let v = UIView(frame: .zero)
let gesture = UITapGestureRecognizer(target: context.coordinator,
action: #selector(Coordinator.tapped))
v.addGestureRecognizer(gesture)
return v
}
class Coordinator: NSObject {
var tappedCallback: ((CGPoint) -> Void)
init(tappedCallback: @escaping ((CGPoint) -> Void)) {
self.tappedCallback = tappedCallback
}
@objc func tapped(gesture:UITapGestureRecognizer) {
let point = gesture.location(in: gesture.view)
self.tappedCallback(point)
}
}
func makeCoordinator() -> GetTapLocation.Coordinator {
return Coordinator(tappedCallback:self.tappedCallback)
}
func updateUIView(_ uiView: UIView,
context: UIViewRepresentableContext<GetTapLocation>) {
}
}
New to SwiftUI and I am trying to combine gestures that allow me to tap anywhere on the screen to add an infinite amount of "Images", but currently the image only stays on screen for a short while. Where am I going wrong? Am I supposed to combine another gesture to get the item to stay on screen whilst adding?
CodePudding user response:
You only have a singular location
, so only one item will ever appear in your example. To have multiple items, you'll need some sort of collection, like an Array.
The following is a pared-down example showing using an array:
struct Hammer: Identifiable {
var id = UUID()
var location: CGPoint
}
struct Level1: View {
@State var hammers: [Hammer] = [] //<-- Start with `none`
var body: some View {
ZStack {
ForEach(hammers) { hammer in // Display all of the hammers
Image(systemName: "hammer.fill")
.resizable()
.frame(width: 30, height: 30)
.position(hammer.location)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.contentShape(Rectangle())
.gesture(DragGesture(minimumDistance: 0).onEnded { value in
self.hammers.append(Hammer(location: value.location)) // Add a Hammer
})
.edgesIgnoringSafeArea(.all)
}
}
Note: I'm unclear on what the GeometryReader
is for in your code -- you declare it, then use UIScreen dimensions -- normally in SwiftUI we just use GeometryReader