---
# System prepended metadata

title: 4가지 트리거 draw 메서드 호출 실험

---

# 4가지 트리거 draw 메서드 호출 실험

1. Moving or removing another view that was partially obscuring your view
![https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/resources/usr/633bdcb0324ce85b6f34f99e/20230410/6433704f324ce85b6f359d4c.png](https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/resources/usr/633bdcb0324ce85b6f34f99e/20230410/6433704f324ce85b6f359d4c.png)

2. Making a previously hidden view visible again by setting its hidden property to NO
![](https://i.imgur.com/bZd5ud8.png)

3. Scrolling a view off of the screen and then back onto the screen
코드에 직접 breakpoint를 걸고 확인해본 결과 **호출되지 않음**.

4. Explicitly calling the setNeedsDisplay or setNeedsDisplayInRect: method of your view
![](https://i.imgur.com/LoMp9dD.png)


</br>

## lldb에서 draw 메서드가 호출되던 이유 🤔
draw 메서드는 trigger가 발생했을 때 일정 조건 아래에서 callback되는 함수입니다. 공식문서 상의 4가지 트리거 중에서 명시적으로 `setNeedsDisplay`가 호출되는 경우를 제외하면 일반적으로는 호출되지 않습니다.

draw 메서드가 1, 2, 3 번의 트리거의 경우 호출되지 않는 이유는 다시 그려야 하는 뷰의 콘텐츠를 실제로 변경하지 않기 때문입니다.

1. 뷰를 부분적으로 가리고 있던 다른 뷰를 이동하거나 제거하면 뷰의 위치만 변경되고 내용은 변경되지 않습니다.
2. Hidden property를 false로 설정하여 이전에 숨겨진 뷰를 다시 표시하도록 해도 뷰의 내용은 변경되지 않습니다.
3. 화면 밖으로 뷰를 스크롤한 다음 다시 화면 위로 스크롤하면 뷰의 위치만 변경되고 내용은 변경되지 않습니다.

위 3가지 경우에 반해 `setNeedsDisplay` 메서드를 호출하면 뷰를 다시 그려야 한다고 알리게 되어 뷰의 다음 Update Cycle 동안 호출될 draw 메서드를 트리거합니다.

물론 트리거 한다고 해서 draw 메서드가 항상 호출되는 것은 아닙니다. 예를 들어, 뷰가 보이지 않거나 다른 뷰에 의해 가려진 경우 시스템에서 뷰를 다시 그리지 않기로 결정할 수도 있습니다. 따라서, `setNeedsDisplay`를 호출하는 것이 뷰를 다시 그려야 함을 알리는 올바른 방법이지만 draw 메서드가 반드시 호출되는 것은 아닙니다.

그렇다면 lldb에서는 왜 draw 메서드에 breakpoint가 걸렸던 걸까요?

### 1️⃣ lldb에서 부분적으로 가리고 있던 뷰를 remove 할 경우
* `스크린샷1`
![](https://i.imgur.com/UQBLhLA.png)
expression 이후 breakpoint에 걸립니다.
</br>

위 스크린샷에서 볼 수 있듯, 처음 lldb를 통해 expression을 진행했을 때 breakpoint에서 잘 멈추었던 것을 확인할 수 있습니다. 하지만 이는 정상적인 동작이 아닙니다. 위에서 설명했듯이, draw 메서드는 트리거가 될 뿐 실제로 호출되지 않아야 합니다. (뷰의 내용이 변하지 않았기 때문에)

이러한 현상은 LLDB가 프로그램의 정상적인 실행을 방해하여 뷰 업데이트 주기를 일시적으로 중단할 수 있기 때문에 발생할 수 있다고 합니다. 즉, LLDB로 디버깅하는 경우 뷰 업데이트 주기가 일반 프로그램 실행에서와 다르게 작동할 수 있습니다.

이 동작은 항상 동작한다고 보장되지 않으며 프로그램 및 디버거의 특정 상황에 따라 달라질 수 있습니다. 따라서 코드에서 이러한 동작을 예상하여 의존하는 것은 바람직하지 않으며 뷰를 다시 그려야 할 필요가 있을 때는 항상 `setNeedsDisplay`를 호출하여 명시적으로 표시해야 합니다.

Breakpoint의 위치에 따라 결과가 달라질 것 같아 추가적으로 코드를 수정하여 실험해 보았습니다! 🤔

### 2️⃣ 버튼을 통해 부분적으로 가리고 있던 뷰를 remove 할 경우
* `스크린샷2`
![](https://i.imgur.com/zGwrsZI.png)
draw 메서드에 breakpoint가 걸려있어도 **멈추지 않습니다**.

이번엔 왜 breakpoint가 작동하지 않았을까요?

1️⃣의 경우와 차이점은 아래 `스크린샷3`을 통해 확인하실 수 있습니다.

* 스크린샷3
![](https://i.imgur.com/i4RcFoh.png)

breakpoint의 위치에 주목해주세요.
lldb에서는 동일하게 draw 메서드에 breakpoint를 걸고 있지만 코드에서는 `viewDidLoad` / `IBAction method` 에 걸려있는 것을 확인할 수 있습니다.

1. `viewDidLoad`에 걸려있는 경우
시뮬레이터에 뷰가 나타나지 않은 상태입니다.
현 상태에서 draw 메서드가 트리거되면 업데이트 사이클에서 뷰가 그려져 있지 않기 때문에 draw 메서드를 호출하게 됩니다.

2. `IBAction method`에 걸려있는 경우
시뮬레이터에 뷰가 나타나 있는 상태입니다.
현 상태에서 draw 메서드가 트리거되면 이미 뷰가 그려진 상태이기 때문에 draw 메서드를 호출하지 않게 됩니다.

이러한 이유로 활동학습 시간에 혼선을 일으킬만한 결과를 보여드리게 되었네요.. 😅
아무쪼록 도움이 되었으면 좋겠습니다.

중요한 점은 뷰를 다시 그려야할 일이 있을 때는 `setNeedsDisplay()`를 호출해야 한다는 점입니다!!

Chat GPT와 기타 블로그 및 공식문서를 참고하여 정리한 내용입니다.
틀린 내용이 있다면 언제든 말씀해주세요!
