본문 바로가기

iOS/WWDC

[WWDC 2018] LLDB 코드 수정 없이 Debugging 해보자!

 

2018’s WWDC was Advanced Debugging with Xcode and LLDB 를 기반으로 한

Xcode and LLDB Advanced Debugging Tutorial Part(1,2,3) 포스트를 정리한 내용입니다.

 

 

시작하기 앞서 Demo Project 환경을 설정합니다.

1. 처음 앱을 시작하면 TableView 에 post 가 보여집니다.

2. TableView Footer 에 Load More Indicator 가 표시됩니다.

3. TableView 하단에 스크롤이 도달하면 다음 페이지를 표시합니다.

4. 풀 다운으로 Post 를 새로고침할 수 있습니다.

5. "Page 0", "100 Posts" 로 현재 페이지 상태를 표시합니다. 

 

버그들! 🥺

1. 풀 다운으로 새로고침을 해도 Post 가 업데이트 되지 않습니다. 

2. 네트워크 연결 문제로 인해 HTTP 요청이 실패 할 때마다 Alert 창이 뜨지 않습니다.

3. 마지막 페이지이면 Load More Indicator 를 표시하지 않습니다.

4. 상단의 "Page 0" 이 업데이트 되지 않습니다.

 

1. 풀 다운으로 새로고침을 해도 Post 가 업데이트 되지 않습니다. 

 

새로운 Post 를 가져오면 상단 우측 "40 Posts" -> "10 Posts" 로 변경되어야 합니다. 

 

 

LLDB Documentation 을 찾아보면서 가장 활용할 수 있는

LLDB Debugging Cheat Sheet 를 소개합니다.

 

expression 은 다시 컴파일하지 않아도 코드를 evaluate 하는데 도움을 줍니다. 

 

Options Automatically continue after evaluating actions 는 BreakPoint가 활성화 된 경우에도 일시 중지하지 않고 expression을 evaluate 한 후 Debugging를 계속 사용할 수 있습니다

 

Demo 에서는 Automatically continue after evaluating actions 옵션을 선택하면 BreakPoint 가 잡히지 않기 때문에 Log 를 출력하도록 하였습니다.

 

오른쪽 하단에 아래와 같이 Log 메시지가 출력될 것 입니다.

 

2. 네트워크 연결 문제로 인해 HTTP 요청이 실패 할 때마다 Alert 창이 뜨지 않습니다.

실제 단말: 네트워크 환경을 설정

시뮬레이터: 맥의 인터넷을 비활성화

 

expression self.presentNetworkFailureAlertController()

 

 

 

3. 마지막 페이지이면 Load More Indicator 를 표시하지 않습니다.

Watch Point 를 설정하면 도움이 됩니다.

 

1. func loadPost() 브레이크 포인트를 설정하고

2. pageNumber 를 watch 하도록 설정합니다.

 

3. Watch가 설정되면 BreakPoint Navigator 에 Watchpoint 항목이 표시됩니다.

 

4. 다음 페이지를 요청하게 되면 pageNumber 를 증가시키는 부분에 브레이크포인트가 동작하는 것을 확인할 수 있습니다.

 

5. expression 을 작성해 줍시다!

expression if (self.pageNumber >= 11) {setToInactiveState()}

 

이제 더 이상 Load More Indicator 가 표시되지 않습니다!

 

4. 상단의 "Page 0" 이 업데이트 되지 않습니다.

Symbolic Breakpoints 는 도움이 됩니다.

Symbolic 에 대한 이해가 필요하시면 여기를 참고해 주세요.

 

 

"Page 0" 이 증가하지 않기 때문에 UILabel setText symbol 에 대한 Breakpoint 를 설정할 수 있습니다.

 

이제 모든 UILabel setText Symbol Breakpoint 가 설정되었습니다!

 

po $arg 는 Argment 보유한 레지스터를 가리킵니다

po $arg1
po $arg2
po (SEL)$arg2
po $arg3

 

 

$arg2는 항상 Objective-C의 selector를 참조합니다.

LLDB 는 이를 모르기 때문에  타입 캐스팅을 해야합니다.

 

모든 UILabel setText: Symbol 에 Breakpoint 가 설정되어서 우리가 찾는 "Page 0" Breakpoint 를 찾기가 어렵습니다!

 

조금 더 범위를 좁혀봅시다!

Page 0은 네트워크로 부터 post 를 가져오는 데 성공하는 업데이트해야 하기 때문에 

self.updateForNetworkCallEnd() Breakpoint를 지정합니다.

breakpoint set --one-shot true -name '-[UILabel setText:]'
--one-shot 한 번만 쓰이고 breakpoint list 에서 사라지는 것입니다. 
즉, 최초 UILabel setText: 를 호출하는 Breakpoint 만 설정된다고 생각하시면 됩니다. 

 

😁 pageNumberLabel 에 "0" 으로 설정하고 있었네요;;;;;

 

 

expression pageNumberLabel.text = String(format: "Page %tu", pageNumber)

 

 

왼쪽 상단에 Page 2,3,4 로 변경되는 걸 확인할 수 있습니다.

 

 

 

마무리

정말 코드 수정 없이 잘 동작하는 앱을 만들었습니다!

 

LLDB Debugger 의 Tutorial 을 확인하시면 정말 많은 Command들이 있습니다.

그러나 이 포스트에서 다루고 있는 내용만으로 생산성을 크게 향상시킬 수 있을 것 같습니다.

 

 

 

 

 

참조: 

 

https://gist.github.com/alanzeino/82713016fd6229ea43a8

https://medium.com/@fadiderias/xcode-and-lldb-advanced-debugging-tutorial-part-1-31919aa149e0

https://developer.apple.com/videos/play/wwdc2018/412