티스토리 뷰

사이드 프로젝트를 하면서 채팅 뷰를 만드는 중인데 onTapGesture 가 동작하지 않는 이슈가 있었다. 

그런데 이게 어떨때는 되고, 어떨때는 안되고, 여러 메시지들 중 안되는 것도 랜덤이고 .. 도무지 파악하기가 어려웠다. 

 

뷰 구조는 이러했다. 

Vstack - List - VStack - HStack - ZStack 인데, 가장 하위에 있는 ZStack 의 TapGesture 가 말썽이였다. 

뭔가 상위 혹은 다른 뷰에서 제스처를 뺏어가는 느낌이긴 한데, 그럴만한 것은 List 밖에 존재하지 않아서 버그인가? 싶었다.

가운데꺼는 제스처가 안돼요

위 gif 에서는 가운데 카드가 탭이 안되지만, 이게 골치아픈게 빌드할 때 마다 안되는 것들이 달랐다. 

몇일동안 이것저것 많은 시도를 해봤지만, 상위의 List 에 있는 스크롤 제스처로 추측된다. 

 

그래서 해결한 방법은 highPriorityGesture 이다. 이번에 알았다.

 

HighPriorityGesture

공식 문서에 따르면 `뷰에 정의된 제스처보다 우선순위가 높은 제스처를 연결` 이라고 한다.

SwiftUI에서 .highPriorityGesture 는 제스처 우선순위를 제어하는 중요한 수정자입니다. 기본적으로 SwiftUI에서 중첩된 뷰에 동일한 제스처가 있을 경우, 항상 자식 뷰의 제스처가 우선시됩니다. 하지만 .highPriorityGesture 수정자를 사용하면 이 기본 동작을 변경하여 부모 뷰의 제스처가 우선적으로 인식되도록 할 수 있습니다. - by ChatGPT

 

항상 자식 뷰의 제스처가 우선시된다고 하는데, 나는 Tap Gesture를 최하단에 달았는데도 뺏긴듯하다.. 뭐지! 진짜 버근가?

하여튼, 기존의 코드를 HighPriorityGesture 를 이용해 변경해보았다. 

ZStack {
	// 무언가 뷰
}
.frame(width: 85, height: 121)
.contentShape(Rectangle())
.onTapGesture {
    tapHandler()
}
.matchedTransitionSource(
    id: id,
    in: namespace
)
.shadow(.default)

 

아래는 변경한 코드

ZStack {
	// 무언가 뷰
}
.frame(width: 85, height: 121)
.contentShape(Rectangle())
.highPriorityGesture(
    TapGesture()
        .onEnded { _ in
            tapHandler()
        }
)
.matchedTransitionSource(
    id: id,
    in: namespace
)
.shadow(.default)

이제 됩니다

 

HighPriorityGesture 만 따로 떼서 보면

struct ContentView: View {
    var body: some View {
        ZStack {
            Text("Hello, World!")
                .onTapGesture {
                    print("hello world tapped")
                }
            
            Text("Text!")
                .onTapGesture {
                    print("Text! tapped")
                }
        }
        .onTapGesture {
            print("ZStack onTapGesture")
        }
    }
}

"Text! tapped" 출력됨

일반 제스처인 경우 가장 자식 뷰인 ZStack 내의 최상단인 Text("Text") 가 탭 되는 것을 볼 수 있다. 

여기서 ZStack의 Gesture 를 HighPriorityGesture 로 변경해보자

 

struct ContentView: View {
    var body: some View {
        ZStack {
            Text("Hello, World!")
                .onTapGesture {
                    print("hello world tapped")
                }
            
            Text("Text!")
                .onTapGesture {
                    print("Text! tapped")
                }
        }
        .highPriorityGesture(
            TapGesture()
                .onEnded { _ in
                    print("ZStack tapped")
                }
        )
    }
}

"ZStack tapped" 출력됨

 

ZStack 의 탭 제스처가 가장 우선시 되어 하위의 제스처를 무시하고 출력되는 것을 볼 수 있다. 

SwiftUI 에서도 이걸 이용하면 세밀하게 제스처를 활용해볼 수도 있을 것 같다!

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/08   »
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
글 보관함