---
# System prepended metadata

title: '[WWDC 2015] What''s New In LLDB'

---

# [WWDC 2015] What's New In LLDB

![](https://i.imgur.com/u1Z8YwZ.jpg)
![](https://i.imgur.com/MwmgIUB.jpg)
![](https://i.imgur.com/dFnICq1.jpg)
![](https://i.imgur.com/u9bXsQG.jpg)

## Compilers in LLDB
![](https://i.imgur.com/OKMuhzf.jpg)
![](https://i.imgur.com/j84YOMY.jpg)

### It’s All Automatic! ...in Swift
![](https://i.imgur.com/eKmpSFp.jpg)
![](https://i.imgur.com/1XsFoQr.jpg)
![](https://i.imgur.com/1JardLG.jpg)
![](https://i.imgur.com/v0wUwjT.jpg)
![](https://i.imgur.com/fomSpf3.jpg)
![](https://i.imgur.com/Og2kBRI.jpg)
![](https://i.imgur.com/jujZDMT.jpg)


![](https://i.imgur.com/4V1ypaD.jpg)

### Handling Errors in Swift Expressions
![](https://i.imgur.com/5GDoICM.jpg)

### Stopping When Swift Errors Occur
![](https://i.imgur.com/SXtFTma.jpg)

### Stopping on Specific Errors
![](https://i.imgur.com/niTZqxR.jpg)

### Of Course, You Can Still Catch Them
![](https://i.imgur.com/jO7WeTs.jpg)

---

## Presentation Is Everything
### Examining Data
![](https://i.imgur.com/bj6fwSr.jpg)

### The “Frame Variable” Command
![](https://i.imgur.com/bN7enGa.jpg)

### The “Expression” Command
![](https://i.imgur.com/GnmI4uy.jpg)

### The “po” Command
![](https://i.imgur.com/HdLOs3c.jpg)

### Formatting Models
![](https://i.imgur.com/QJTYnsu.jpg)
![](https://i.imgur.com/t6HZJFF.jpg)

### In-Process Swift Formatting
![](https://i.imgur.com/FbExa3g.jpg)
![](https://i.imgur.com/DDfYFjC.jpg)

### CustomStringConvertible
![](https://i.imgur.com/MeF319P.jpg)

### CustomDebugStringConvertible
![](https://i.imgur.com/e0T8Uah.jpg)

### CustomPlaygroundQuickLookable
![](https://i.imgur.com/kcdH7Au.jpg)
![](https://i.imgur.com/RwE3V5y.jpg)

### CustomReflectable
![](https://i.imgur.com/rmlrFtr.jpg)

### Temperature Data
![](https://i.imgur.com/lk8Gvi6.jpg)
![](https://i.imgur.com/ZyA7pwp.jpg)

### Step 1: Time on One Line
![](https://i.imgur.com/cmrgRL5.jpg)

### Step 2: Fahrenheit Degrees
![](https://i.imgur.com/2NCT3Kl.jpg)

### Temperature Data
![](https://i.imgur.com/nwKrtMb.jpg)

### At Runtime Too!
![](https://i.imgur.com/11lHkAW.jpg)

### And in Playgrounds!
![](https://i.imgur.com/S0KyLWB.jpg)

### Summary
![](https://i.imgur.com/iLbrfaU.jpg)

### More Information
![](https://i.imgur.com/f2MOmks.jpg)

### Related Sessions
![](https://i.imgur.com/QosVqAz.jpg)



LLDB에는 장황한 구문처럼 보일 수 있지만 실제로는 여러 가지 단축키가 있으므로 'help'를 입력하도록 요청할 수 있기 때문에 이를 이해하는 것이 중요합니다.

그리고 이 프레젠테이션 전체에서 다음 표기법을 사용하여 설명합니다.
도움말은 실제로 첫 번째 고유 시퀀스로 축약될 수 있습니다.
따라서 이 경우 H는 도움을 불러일으키기에 충분합니다.
더 중요한 것은 expression-O-- 와 같은 보다 정교한 예제의 경우 '표현식 평가하기'를 의미하며, 그 자체를 설명하는 메서드를 보낸 다음 표현식 다음에 더 이상 옵션이 없는 개체인 것처럼 결과를 알려주십시오. 하지만 PO를 입력하면 됩니다.
PO는 왼쪽에 있는 모든 항목의 약칭인 편리한 별칭입니다.
따라서 도움말에 익숙해지면 별칭을 사용하는 방법을 배워야 합니다. 별칭은 LLDB의 일부 강력한 기능에 가장 빠르게 접근할 수 있는 방법이기 때문입니다.
데이터에 대해 알려주는 것이 디버깅 경험에 절대적으로 중요하기 때문에 데이터 형식도 개선했습니다.
따라서 set 및 NS Index Path와 같은 유형에는 기본 표현의 원시 덤프를 표시하는 대신 데이터를 이해하는 데 도움이 되는 기본 형식이 있습니다.
표현식에 대한 Printf 프로토타입, printf와 관련된 표현식을 평가하려고 시도했다면 약간 의심스러운 결과를 보았을 것입니다.
대부분의 경우 디버거가 알지 못하고 printf를 알지 못하는 선언에 대해 표현식에 대해 많은 가정을 하려고 하기 때문입니다.
따라서 가변 함수, 즉 가변 개수의 인수를 취할 수 있는 함수라는 것을 몰랐고 특히 64비트 장치에서 이러한 인수를 올바르게 전달하는 방법을 몰랐습니다.
C 및 Objective-C에 대한 printf와 관련된 모든 표현식이 바로 사용할 수 있도록 수정되었습니다.
그리고 마지막으로, 정말 마지막으로 이번에는 분해 형식을 개선하여 그 어느 때보다 읽기 쉽게 만들었습니다.
더 흥미로운 개선 사항 중 일부를 파고들면 올 봄에 여러분이 알지 못할 수도 있는 중단점 개선 사항이 만들어졌습니다.
특히 이제 중단점의 이름을 지정할 수 있습니다.
이름이 고유할 필요가 없고 단일 중단점에 여러 이름을 적용할 수 있다는 것을 깨닫기 전까지는 명명된 중단점이 다른 중단점보다 사용하기 쉬운 이유가 분명하지 않을 수 있습니다.
태그와 유사하게 생각할 수 있습니다.
그리고 모든 중단점 명령은 이러한 이름을 사용합니다.
따라서 중단점 세트와 대시 N, 대문자 N 다음에 이름, 선택적으로 다른 대시 대문자 N 및 추가 이름 등을 제공하여 중단점을 설정할 수 있습니다.
그러나 더 중요한 것은 일단 중단점 또는 여러 중단점에 이름을 지정하면 다른 모든 명령으로 해당 중단점에 대해 작업할 수 있다는 것입니다.
Breakpoint enable name은 해당 이름을 공유하는 모든 중단점을 활성화하거나 다시 해당 태그로 생각합니다.
이는 이제 LLDBinit에서 중단점을 설정할 수 있다는 사실로 인해 더욱 흥미로워졌습니다.
LLDBinit에 익숙하지 않다면 이것은 LLDB에게 알려주는 마침표가 있는 접두사로 시작하는 파일 이름입니다. 여기에 LLDB 세션을 시작할 때마다 실행할 여러 명령이 있습니다.
따라서 이것을 사용하면 LLDB가 시작될 때 기본 중단점 집합을 만들 수 있으며 실제로 대상을 만들기 전에 설정한 모든 중단점은 만드는 모든 대상에서 상속됩니다.
따라서 이 두 가지를 결합하면 이 줄을 따라 LLDBinit를 작성할 수 있습니다.
일련의 중단점, -n malloc이라는 이름의 모든 것, breakpoint -n이라는 이름의 모든 것, 모든 중단점 메모리의 이름을 지정한 다음 비활성화합니다.
그리고 이것이 나에게 주는 것은 그 이후에 사용하는 세션에서 '브레이크포인트 활성화 메모리'를 입력하기만 하면 모든 메모리 처리 중단점을 얻을 수 있는 편리한 방법입니다.
따라서 항상 액세스하고 싶은 편리한 중단점 집합이 있고 이제 기억하기 쉬운 이름을 지정할 수 있습니다.
그러나 물론 여러분은 우리가 이미 수행하고 이미 출하한 것에 대해 배우기 위해 여기에 온 것이 아니라 이제 막 미리 보기 시작하는 것에 대해 배우기 위해 여기에 있습니다.
Xcode 7, 정말 중요한 릴리스, 여기에 많은 개선 사항이 있습니다.
특히 표현 평가.
그리고 Sean은 이에 대해 더 깊이 있게 이야기할 것입니다.
Swift 2 지원은 물론 언어가 계속 발전하고 모듈에 대한 고급 처리 측면에서 Objective-C를 지원하기 때문입니다.
이 중 일부는 우리가 깊이 있게 다룰 것이지만, 그 중 일부는 실제로 배후에서 다루고 있습니다.
파헤쳐보면, 예를 들어 Xcode 7에서 우리는 모듈에 대해 알고 있기 때문에 실제로 모듈에 대한 디버그 정보를 한 번 빌드한 다음 다른 곳에서는 복제할 수 없다는 것을 알 수 있습니다.
이를 통해 디버그 정보의 크기를 크게 줄이고 컴파일 성능을 향상시킬 수 있습니다.
실제 .dSYM 파일에 들어가면 해당 .dSYM 파일에는 필요한 모든 것이 포함됩니다.
그러나 여기에는 하나의 정의 규칙 덕분에 C++ 유형에 대한 정보를 복제하지 않는 것과 같은 편리한 다른 최적화도 포함되어 있습니다.
사실, 특히 C++ 프로젝트의 경우 디버그 정보가 Xcode 6의 6분의 1 크기로 축소되는 것을 보았습니다.
또한 다양한 방식으로 데이터 형식을 개선했습니다.
벡터 유형은 이제 Objective-C와 Swift 모두에 대해 고유한 자동 데이터 형식을 갖습니다.
그리고 아마도 가장 중요한 것은 Swift에 사용자 정의 유형이 있는 경우 이제 Swift 코드를 작성하여 표시되는 방식을 사용자 정의할 수 있다는 것입니다.
그리고 Enrico는 이에 대해 깊이 있게 이야기할 것입니다.
주소 새니타이저에 대한 지원을 LLDB에 통합했습니다.
따라서 주소 새니타이저는 유효하지 않은 메모리를 참조할 때 알려줄 뿐만 아니라 메모리에 대해 질문할 수도 있습니다.
예를 들어, LLDB 콘솔에서 바로 메모리가 할당된 위치 또는 할당 해제된 시간을 확인하기 위해 메모리 기록을 요청할 수 있으므로 명령의 메모리 계열은 자세히 살펴보고 도움말을 볼 수 있습니다. .
유형 조회 명령도 추가했습니다.
type lookup 명령을 사용하면 시스템의 모든 유형에 대한 정보를 얻을 수 있습니다.
기본적으로 유형의 내용을 상기시키기 위해 디버거에서 바로 얻을 수 있는 헤더와 같은 표현입니다.
따라서 LLDB 프롬프트에서 '유형 조회'를 입력하고 유형 이름을 입력하면 해당 유형에 대한 간략한 설명을 얻을 수 있습니다.
이 경우 Swift의 오류 처리 메커니즘에서 사용하는 새로운 오류 유형입니다.
EDAM 유형을 사용하는 한 일반적으로 구현된 한 쌍의 속성이 배후에서 있지만 그럼에도 불구하고 콘솔에서 바로 세부 정보를 볼 수 있습니다.
마찬가지로 'Comparable'과 같은 유형에 관심이 있는 경우 프로토콜입니다.
이 프로토콜은 실제로 다른 두 프로토콜에서 파생되어 Equatable이 등호 연산자를 얻는 곳임을 알 수 있습니다.
밑줄 Comparable은 기본 미만을 얻는 곳이며 파생된 연산자는 Comparable 프로토콜의 일부입니다.
그래서 여기에서 얻을 수 있는 편리한 정보가 많이 있습니다.
그리고 다른 모든 것과 마찬가지로 'type lookup' 전체 명령을 입력할 필요가 없음을 상기시키십시오. 이 명령을 사용하려면 TY 공백 L이면 충분합니다.
그러나 더 깊이 파고들기 위해, 특히 표현을 평가하는 방법에 대해 이야기하기 위해 Sean Callanan을 초대하고 싶습니다.
숀 캘러넌: 안녕하세요.
LLDB의 컴파일러에 대해 말씀드리고 싶습니다.
이제 많은 컴파일러 세션이 있다고 스스로에게 말할 수 있습니다.
내가 컴파일러에 관심을 갖는 이유는 무엇입니까? 컴파일러는 LLDB의 중요한 부분입니다.
이는 LLDB를 강력하게 만드는 요소이며 LLDB를 사용하기 쉽게 만드는 요소입니다.
컴파일러는 프로그램이 작동하는 방식, 데이터를 배치하는 방식, 이 변수를 보거나 이 함수를 호출하고 싶다고 말할 때 의미하는 바에 대해 고유한 이해를 갖고 있기 때문에 정말 강력합니다.
컴파일러가 중요한 또 다른 이유는 디버거로 작업하기 쉽기 때문입니다.
무언가를 인쇄하려면 입력하는 데 익숙한 코드를 사용하고 이를 expression 명령에 전달하면 컴파일러가 거기에서 인계받습니다.
그래서 오늘은 컴파일러 통합과 관련된 두 가지 중요한 영역에서 개선된 사항에 대해 말씀드리고자 합니다.
우선 오랜 기간 Objective-C 개발자 여러분께 희소식을 전해드립니다.
그런 다음 이 시점에서 여러분 모두가 되기를 희망하는 모든 Swift 개발자에게 우리가 거기에서 만든 개선 사항에 대해서도 말할 것입니다.
Objective-C를 시작하겠습니다.
이제 LLDB에는 두 개의 개별 컴파일러가 포함되어 있습니다.
Clang은 강력한 Objective-C 컴파일러이자 작년부터 Swift 컴파일러입니다.
Objective-C 컴파일러 지원은 수년에 걸쳐 개선되어 왔으며 훌륭한 새 기능을 추가해 왔습니다.
예를 들어 Objective-C 런타임 통합이 있습니다.
따라서 디버그 정보에 없는 Objective-C 런타임에 정보가 있는 경우 컴파일러에 이를 제공하여 특별한 작업을 수행하지 않고도 많은 클래스를 사용할 수 있다는 것을 알고 있습니다.
물론 작년에 우리는 Swift 컴파일러를 LLDB에 도입했습니다.
그리고 Swift 컴파일러는 이미 매우 강력한 도구입니다.
그리고 우리는 Swift 컴파일러를 통합하면서 배운 많은 교훈을 사용했고 이 둘을 함께 개선했습니다.
Objective-C의 관점에서 표현식 파서가 Swift와 어떻게 작동하는지 이야기해 봅시다.
간단한 인쇄 명령을 살펴보겠습니다.
이제 p 바로 가기를 사용하고 있기 때문에 여기에서 인쇄라고 말합니다.
그것이 실제로 의미하는 것은 표현입니다.
대시 대시를 확인하십시오.
이는 p 명령 이후의 모든 것이 코드화되어야 함을 의미합니다.
이 방법으로 명령에 추가 옵션을 전달할 수 없습니다.
Enrico가 당신에게 말할 것과 Kate가 전에 당신에게 보여준 것처럼 다른 방법이 있습니다.
이제 루프를 실행하고 매번 루프 카운터를 인쇄하는 몇 가지 간단한 코드가 있습니다.
그리고 실제로 실행하면 예상했던 수치가 나옵니다.
이게 왜 멋져? LLDB와 프로그램은 별개의 프로세스입니다.
LLDB에는 내부에 신속한 컴파일러가 있습니다.
프로그램이 이미 실행 중이지만 LLDB의 도움으로 Swift 컴파일러는 실행하기 위해 프로그램에 방금 입력한 코드를 삽입할 수 있습니다.
루프 카운터를 인쇄하는 것을 좋아한다면 멋진 방법입니다.
그러나 디버깅에 조금 더 많은 것이 있습니다.
Swift는 변수와도 작동합니다.
일부 코드를 입력합니다.
그리고 배열의 내용이 인쇄됩니다.
이제 이 배열은 프로그램에 있는 데이터의 일부일 뿐입니다.
그리고 LLDB는 해당 데이터를 컴파일러에 표시하여 사용자가 예상하는 코드를 생성할 수 있도록 합니다.
정말 빨리 이야기하고 싶은 또 다른 것이 있습니다.
이것이 Swift가 SDK와 작동하는 방식입니다.
NSApplication.sharedApplication과 같은 표현식을 입력하면 먼저 예상한 대로 NSApplication.sharedApplication이 표시됩니다.
그러나 LLDB가 하는 일은 나가서 그것을 포함하는 SDK 모듈을 찾아 컴파일러에 액세스 권한을 부여한 다음 컴파일러가 NSApplication을 찾고 sharedApplication을 사용하는 방법을 파악하는 것입니다.
그것은 모두 훌륭하고 Swift에서 자동입니다.
Objective-C에서 항상 작동하는 것은 아닙니다.
따라서 Objective-C에서 이 모든 것을 시도해 보겠습니다. NSLog를 시도하는 것이 디버거에서 들리는 것처럼 쉽지 않다는 것을 알고 있기 때문에 이 순간에 여러분 중 일부는 약간 불안해할 수 있습니다.
과거에 NSLog에 입력했을 때 다음과 같은 오류를 본 적이 있습니다. NS 로그에 알 수 없는 반환 유형이 있습니다.
SDK에는 NSLog에 대한 정의가 있기 때문입니다.
그러나 LLDB가 보는 것은 기호의 디버그 정보에 있는 것뿐입니다.
이 경우 표시되는 것은 기호뿐입니다.
그 기호는 반환 유형이 무엇인지 모르고 형식 문자열을 취한다는 것조차 모릅니다.
글쎄, 좋은 소식은 우리가 그것을 고쳤다는 것입니다.
SEAN CALLANAN: NSLog는 예상대로 작동합니다.
이제 조금 더 손이 많이 가는 것을 시도해 보겠습니다.
NSMakeRect를 인쇄합니다.
잠깐만! 이게 왜 언더핸드인가요? 바로 프레임워크에 있습니다.
불행히도 이 식별자는 존재하지 않는 것 같습니다.
이제 NSLog를 사용하고 결과를 캐스팅하면 예, 사용할 수 있다는 것을 알 수 있습니다.
그러나 NSMakeRect에서는 그렇게 할 수도 없습니다.
NSMakeRect가 NS-Inline으로 정의되어 있기 때문입니다.
그것에 대한 상징은 없습니다.
LLDB가 보는 것은 아무것도 아닙니다.
좋은 소식.
더 이상 문제가 없습니다.
SEAN CALLANAN: 고통이 하나 더 남았습니다.
이제 이전 NSApplication sharedApplication 사례를 살펴보겠습니다.
물론, 해당 표현식을 직접 실행했다면 예, Objective-C에서 작동할 것입니다.
내 말은, 우리는 Objective-C 런타임 통합에 대해 작업해 왔습니다.
그러나 undo.Manager를 실행하려고 하면 런타임이 모든 것을 알려주지 않는다는 것을 빠르게 알 수 있습니다.
무슨 일이야? SDK에서 sharedApplication은 NSApplication 스타를 반환합니다.
그러나 런타임을 보면 반환되는 것은 일반 Objective-C 개체인 id입니다.
좋은 소식.
더 이상 문제가 되지 않습니다.
사실 우리는 그 포인터가 널 입력 가능하다는 것과 같이 SDK에서만 찾을 수 있는 정보를 봅니다.
이것은 Objective-C에도 포함되는 Swift에 대한 새로운 훌륭한 SDK 지원 중 일부입니다.
그러나 정보는 바로 거기에 있습니다.
그리고 그것이 우리가 여기에 적용한 철학입니다.
SDK에서 바로 읽으십시오.
귀하의 코드는 항상 LLDB에서 작동했습니다.
우리는 지역 변수, 함수, 자신의 클래스에 대해 알고 있었습니다.
반면에 SDK 기능에는 보시다시피 문제가 조금 더 있었습니다.
NSView 및 NSApplication과 같은 SDK 클래스가 있습니다. 예, 우리는 그들을 보았지만 런타임 통합으로 인해 거기에 약간의 별표가 있었습니다.
이제 SDK 상수, 표현식에서 NSASCIIStringEncoding을 사용해 본 적이 있다면 결코 날아간 적이 없다는 것을 알 것입니다.
그리고 두 숫자 중 가장 큰 숫자를 사용하기 위해 int-max 및 max와 같은 매크로를 사용하려고 시도했지만 아무데도 가지 않았습니다.
글쎄, 그 모든 것이 최신 LLDB에서 수정되었습니다.
SEAN CALLANAN: 성가신 별표도 제거했습니다.
SEAN CALLANAN: 이제 이 기능을 사용하려면 39.95달러의 손쉬운 월별 결제를 몇 번이나 해야 합니까? 좋은 소식입니다. 모두 무료이며 @import AppKit을 사용합니다.
내가 관심 있는 프레임워크를 가져오라는 표현식을 실행하기만 하면 AppKit을 가져오거나 두세 명의 iOS 프로그래머가 UIKit을 가져오면 작동합니다.
이제 우리는 Swift와도 가만히 있지 않았습니다.
Swift 2.0은 훌륭한 오류 처리 지원을 제공하며 LLDB는 바로 당신이 기대하는 대로 지원합니다.
우리는 Swift 오류를 처리할 수 있으며 표현식에서 오류를 던질 수 있는 함수를 호출할 때 'try'를 호출할 필요가 없습니다.
그 이유는 우리가 당신을 위해 물건을 잡기 때문입니다.
이 함수를 'throws'라고 입력하고 이를 표현식에 전달하면 p 명령과 동일함을 알 수 있습니다.
해당 함수가 던진 오류가 포함된 오류 변수가 생성됩니다.
REPL에서도 이 작업을 수행할 수 있습니다.
REPL 프롬프트에서 동일한 작업을 수행하면 오류 변수가 표시됩니다.
이제 LLDB 지원에 대해 조금 더 자세히 살펴보겠습니다.
즉, 결과 오류가 무엇인지 항상 보고 싶지는 않습니다.
그 오류를 던진 코드가 무엇인지 알고 싶습니다.
자, Objective-C에서 이 작업을 수행한 방법은 중단점을 사용하는 것입니다.
특히 Objective-C 예외에 중단점을 설정합니다.
이 작업을 수행한 방법은 중단점 설정 명령을 사용하는 것입니다.
Objective-C 예외에 대한 중단점을 설정하도록 지정하면 해당 중단점이 자동으로 설정됩니다.
이제 Objective-C 코드가 예외를 throw하려고 할 때마다 중지됩니다.
Swift 오류에 대해서도 동일한 작업을 수행할 수 있습니다.
Objective-C를 Swift로 바꾸기만 하면 프로그램에서 Swift 오류를 발생시키려고 할 때마다 중지됩니다.
하지만 당신이 할 수 있는 또 다른 멋진 일이 있습니다.
즉, 특정 유형의 오류에서 중지할 수 있습니다.
이것은 우리가 Swift에서 지원하는 것입니다.
그리고 수행하는 방법은 매우 간단합니다. 어쨌든 표현식 중단점을 설정하는 방법과 매우 유사합니다.
포착하려는 오류의 유형 이름을 지정하는 대시 O 매개변수를 사용합니다.
이제 그렇게 하면 관심 있는 오류 유형이 throw될 때만 중지됩니다.
이제 마지막으로, 물론 일반 코드에서와 같은 방식으로 여전히 오류를 잡을 수 있습니다.
결국 REPL은 부분적으로 언어가 작동하는 방식을 배우고 탐구하는 방법으로 사용됩니다.
Foundation을 가져와 NSError를 가져온 다음 NSError를 발생시키는 코드를 작성하면 해당 NSError를 잡아서 인쇄할 수 있습니다.
그렇게 하면 출력은 자신의 프로그램에서 잡은 것과 정확히 동일합니다.
그러니 두 가지를 기억하고 나가시길 바랍니다.
우선, 모듈 가져오기를 추가하고, 두 번째로 LLDB에서 오류 처리를 시도해 보십시오.
하기 좋은 곳입니다.
이제 프로그램에 수행할 작업을 지시하는 방법이 아니라 프로그램이 완료된 후 생성하는 정보를 인쇄하는 방법에 대해 자세히 알아보려면 Enrico Granata를 호출하고 싶습니다.
엔리코 그라나타: 안녕하세요! 나는 오늘 아침에 연구소에 있었다.
그리고 우리는 문제를 살펴보려고 했고 한 가지 문제가 발생했습니다. 왜 이 변수를 볼 수 없습니까? 무슨 일이야? 그리고 그것을 이해하는 데 도움이 되도록 몇 가지 명령을 시도했습니다.
표현을 시도하고 PO를 시도하고 프레임 변수를 시도했습니다.
그리고 사람들은 일반적으로 이 시점에서 묻습니다. 거의 동일한 작업을 수행하는 명령이 왜 그렇게 많은가요? 내 데이터를 보고 내 프로그램에서 무슨 일이 일어나고 있는지 확인하십시오.
자, 여기 있는 여러분 모두는 이제 내부 특종을 얻으십시오.
LLDB에서 데이터를 볼 수 있도록 하는 명령을 살펴보겠습니다.
세 가지가 있습니다.
프레임 변수, 표현식 명령인 p 명령, 표현식 대시 대문자 O, 이전에 말했듯이 po 명령으로 알고 있습니다.
첫 번째, 프레임 변수 명령입니다.
입력할 때 frv로 줄일 수 있는 프레임 변수 명령은 거의 Xcode 변수 보기입니다.
모든 지역 변수를 볼 수 있습니다.
이를 통해 로컬 변수 중 일부만 볼 수 있으며 선택적으로 대시 대시 형식 플래그를 사용하여 서식을 적용할 수도 있습니다.
다시 돌아가서 강조하고 싶은 한 가지는 첫 번째 출력에서 Tuple을 볼 때입니다. 즉, 집계이며, 다른 개체를 포함하는 개체입니다.
그 집합체 안에 있는 것들을 우리는 아이들이라고 부릅니다.
expression 명령어는 이번 세션에서 많이 본 명령어입니다.
정말 짧게 하겠습니다.
물론 expression 명령을 사용하면 짐작할 수 있듯이 간단한 산술 연산을 수행할 수 있습니다.
이전 결과를 사용하고 실제로 더 많은 작업을 수행하는 것이 완전히 가능합니다.
물론 expression 명령은 결과의 사용자 지정 형식 지정을 수행하는 방법도 알고 있습니다.
다시 한 번 지적하고 싶은 것은 아이들입니다.
세 번째 명령은 po 명령입니다.
이것은 아마도 Objective-C 개발자라면 누구나 할 수 있는 명령일 것입니다. 저는 Objective-C 코드 이전에 꽤 많이 추측하고 있으며 po 명령을 알고 있습니다.
개체를 만들고 설명을 인쇄할 수 있습니다.
NSArray를 생성하거나 기존 NSArray를 인쇄하면 그 내용을 볼 수 있습니다.
또는 단순히 문자열에 대해 작동합니다.
따라서 세 가지 명령.
아마 지금쯤 짐작하셨겠지만 모두 똑같은 일을 하지는 않습니다.
사실, 그것들은 다소 유사하고 전혀 동일하지 않습니다.
예를 들어, expression 명령과 po 명령은 '내 코드 실행' 명령입니다.
어떤 코드를 입력하든 이 명령이 실행됩니다.
그러나 프레임 변수 명령과 표현식 명령은 2단계를 다르게 수행합니다.
결과를 보여줘야 할 때 LLDB 포맷터 시스템을 사용합니다.
우리는 지난 WWDC 세션에서 LLDB 포맷터 시스템에 대해 꽤 많이 이야기했습니다.
그리고 당신은 완전히 그들을 확인하러 가야합니다.
그러나 간단히 말해서 LLDB는 몇 가지 기본 제공 시스템 유형에 대한 지식을 가지고 있으며 자동으로 형식을 지정합니다.
NSArray, 문자열이 있는 NSDictionaries.
그리고 파이썬으로 작성된 자신만의 형식을 제공하는 것이 가능합니다.
반면에 po 명령은 LLDB 포맷터를 사용하지 않습니다.
po 명령은 실제로 보여야 하는 결과를 생성하기 위해 뒤에서 더 많은 추가 코드를 실행합니다. Objective-C 클래스 중 하나에서 적어도 하나의 설명 메서드를 작성했을 수 있으며 오, 그것이 po가 인쇄하는 것임을 깨달았을 것입니다.
이제 실제로 개체를 가져와 데이터를 생성하는 이 두 가지 모델에 대해 잠시 생각해 보시기 바랍니다.
LLDB 포맷터의 모델은 우리가 '아웃 오브 프로세스' 포맷 모델이라고 부르는 것입니다.
왜요? 포맷터는 프로세스 외부에 있기 때문입니다.
디버거에 지식을 구축했거나 개체를 나타내기 위해 일부 Python 스크립트를 가져왔습니다.
다른 언어, 다른 범위에 있는 다른 파일입니다.
반면에 외부 포맷터는 Dugger에 있습니다.
그 사람이 디버거가 가지고 있는 프로그램에 대한 모든 지식에 액세스하는 것은 정말 쉽습니다.
그것은 당신의 과정에 대한 조감도와 같습니다.
그 때문에 이런 종류의 포맷터가 프로그램 상태가 변경되지 않았는지 확인하는 것도 정말 쉽습니다.
디버거에서 데이터를 본 결과 프로그램의 상태를 변경하고 싶지 않습니다.
디버거는 스테이지 인스펙터와 비슷합니다.
사물을 보고 바꾸지 않으려고 합니다.
다른 모델인 po 모델인 '설명 방법 쓰기' 모델은 처리 중인 형식화 모델입니다.
데이터와 포맷터를 함께 작성하고 동일한 언어로 작성합니다.
같은 파일에 쓸 수도 있습니다.
그리고 포맷터는 응용 프로그램에서 실행되는 코드일 뿐이므로 응용 프로그램의 개체 모델에 쉽고 완벽하게 액세스할 수 있습니다.
그러나 큰 힘에는 큰 책임이 따른다.
포맷터가 프로그램의 상태를 변경하지 않는지 확인하고 싶습니다.
표현하려는 개체를 변경하는 포맷터에서 아무 것도 하지 않았는지 확인하고 싶습니다.
네, Objective-C에는 in-process 형식화 모델이 있습니다.
설명 메서드를 작성할 수 있으며 디버거가 이를 선택합니다.
스위프트는 어떻습니까? 그리고 다시 한 번, 이 방에 계신 여러분은 내부자 특종을 얻습니다. Swift는 처음부터 in-process 형식화 모델을 가지고 있었습니다.
하지만, 어디에 있습니까? 어떻게 사용합니까? 여러분 모두 Swift 놀이터를 사용해 보았으면 합니다.
Swift 플레이그라운드를 사용한 적이 있다면 Swift in-process 형식화 모델을 사용한 것입니다.
그것은 처음부터 거기에 있었습니다.
그래서 새로운 것은 무엇입니까? 이제 Xcode 7에서 동일한 모델을 사용하여 공개 API로 만듭니다.
사용하실 수 있습니다.
그리고 여전히 플레이그라운드에 전원을 공급하지만 이제는 LLDB po 명령에도 전원을 공급합니다.
이제 Swift 객체에 적합한 Swift 포맷터가 생겼습니다.
어떻게? 표지 아래를 조금 살펴보겠습니다.
이 모델은 네 가지 프로토콜을 기반으로 합니다.
이것은 그들의 이름입니다.
네, 저는 네 가지 프로토콜을 말했습니다.
그리고 그들의 이름도 꽤 길다.
그러나 나는 그것에 대해 너무 걱정하지 않을 것입니다.
이 모델에 부분적으로만 옵트인하는 것이 가능합니다.
네 가지 프로토콜이 모든 프로토콜을 준수해야 한다는 의미는 아닙니다.
원하는 결과를 얻기 위해 하위 집합을 선택할 수 있습니다.
ENRICO: 그것들을 따르고, 그 일을 하고, 이익을 얻으십시오.
프로토콜을 살펴보자.
CustomStringConvertible은 내 개체를 문자열로 인쇄하는 방법을 알려주는 프로토콜입니다. LLDB에만 해당되는 것은 아닙니다.
또한 스위프트에게 알려줍니다.
어떻게? Swift 인쇄 기능과 Swift 문자열 보간 기능은 모두 CustomStringConvertible 프로토콜을 사용합니다.
많은 이점이 있습니다.
그것을 얻기가 얼마나 어려울 수 있습니까? 꽤 쉽습니다.
나 자신을 bash를 준비하고 있기 때문에 맥주 노래의 병을 나타내는 데이터 구조가 있습니다.
그리고 가사를 인쇄하고 싶습니다.
나는 그 인스턴스를 만들고 벽에 맥주 병이 몇 병 있는지 말합니다.
하지만 그것은 내 앱의 모든 것이 잘 작동할 때를 위한 것입니다.
디버깅 중이라면 조금 더 많은 정보가 필요할 수 있습니다.
이것이 Custom Debug String Convertible이 시작되는 곳입니다.
개체의 디버거 특정 표현입니다.
디버거별 의미는 실제로 앱에 달려 있습니다.
그것은 실제로 개체 모델의 의미에 달려 있습니다.
그러나 힌트로 debugPrint 함수는 기본적으로 이 프로토콜을 선택합니다.
물론 print와 debugPrint는 선호하는 것이 없으면 다른 적합성으로 대체됩니다.
이 작업을 수행하는 방법? 아주 간단합니다.
맥주 병을 확장합시다.
디버깅을 하고 있기 때문에 벽에 붙어 있는 맥주 병에 대해 조금 더 알고 싶습니다. 그래서 그것들이 모두 제대로 스타우트인지 확인할 수 있습니다.
세 번째 프로토콜은 Custom Playground Quick Lookable입니다.
이름에서 알 수 있듯이 이 프로토콜은 특히 놀이터용입니다.
놀이터에서 개체에 대한 풍부한 그래픽 표현을 제공하기 위한 것입니다.
당신은 예를 원하십니까? 확실한 것.
사람을 나타내는 데이터 구조를 작성한 다음 해당 유형의 개체를 만든 결과로 내 놀이터 사이드바에 표시되는 사람의 묘사를 얻을 수 있습니다.
실망시켜드려서 정말 죄송합니다. 저는 정말 이런 일이 일어나게 하고 싶었습니다.
그러나 불행히도 내 사람과 함께 한 티셔츠는 회의에서 판매되지 않습니다.
죄송합니다. 하지만 만회할 것이 있습니다. 로트의 마지막 프로토콜인 Custom Reflectable 프로토콜입니다.
이를 통해 우리는 완전히 사용자 정의된 하위 계층 구조를 만들 수 있습니다.
네, '어린이'라는 단어로 돌아가겠다고 했고 그렇게 했습니다.
내가 완전히 사용자 정의된 하위 계층 구조를 말할 때 내 말은 내가 새로운 것을 만들 수 있다는 것입니다. 내 개체에 대한 새로운 구조를 만들 수 있습니다.
나는 언어를 말할 수 있고, 디버거에게 말할 수 있고, 놀이터를 말할 수 있습니다. 이것이 내 객체가 실제로 만들어지는 것입니다.
이렇게 봐야 합니다.
그리고 이것을 하는 방식으로, 객체의 구조를 Swift에 설명하려고 할 때 거래하는 통화를 미러, 반사 가능한 미러라고 합니다.
더 이상 고민하지 않고 예를 보겠습니다.
온도 샘플을 수집하는 작업을 하는 응용 프로그램이 있습니다.
그것은 몇 가지 데이터 구조를 가지고 있습니다.
하나는 시간의 한 순간을 설명하고 다른 하나는 주어진 시간 동안 이것이 내가 얻은 온도 정보라고 말합니다.
그리고 우리는 물론 온도 샘플을 얻었습니다.
이제 이 앱을 디버깅하고 있습니다.
무슨 일이 일어나고 있는지, 어떻게 샘플을 처리하는지 보려고 합니다.
그래서 나는 po 온도를 말합니다.
그리고 그것이 내가 얻은 것입니다.
솔직히 알고보면 디폴트치고는 나쁘지 않다고 합니다.
그러나 나는 즉시 이것에 대해 변경하고 싶은 몇 가지 사항을 봅니다.
왜 두 줄에 시간을 누적합니까? 정말 한 줄에 다 나왔으면 좋겠어요.
그리고 그것이 am/pm 형식이라면 그것도 좋을 것입니다. 그리고 그 온도, 저는 그것을 보고 '그게 어느 정도의 스케일인가요? 나도 몰라.
Kelvin입니까, Reaumur입니까, Rankine입니까? 우리는 미국에 있고 화씨 학위를 원합니다.
ENRICO GRANATA: 좋은 소식은 이 모든 것을 두 단계로 고칠 수 있다는 것입니다.
이것이 나를 위해 일어난 일입니다.
NSDate 포맷터를 사용했습니다.
내 애플리케이션 내에서 실행해야 하기 때문에 이 개체의 형식을 지정하기 위해 실행 중인 코드는 실제로는 일반적인 Swift 코드이기 때문에 일반적으로 내 앱의 일부로 작성하는 코드일 뿐입니다. 프레임워크, 라이브러리, 기술이 무엇이든 간에 앱은 일반적으로 이 작업을 완료하는 데 사용합니다. 저는 그냥 포맷터에서 사용할 수 있습니다.
이 경우 NSDate 포맷터.
2단계, 화씨 온도를 설정해 보겠습니다.
어떻게 합니까? 우리는 거울을 만듭니다.
여기 있습니다.
이제 우리는 우리의 온도 데이터 객체가 세 가지의 컨테이너로 구성되어 있다고 말합니다.
시간, 섭씨 온도 및 화씨 온도입니다.
시간은 개체 내부에 저장된 실제 시간 데이터의 문자열 보간입니다.
그리고 문자열이 삽입되고 사용자 지정 문자열 변환 적합성을 제공했기 때문에 자동으로 선택됩니다.
여기서 주목할 가치가 있는 한 가지는 두 눈금을 모두 얻을 때 결과 인쇄에 대해 섭씨와 화씨를 모두 얻을 때 개체 내부에 저장된 값을 변경하지 않는다는 것입니다.
물론, 당신은 말하지 않습니다.
글쎄요, 실제로는 in-process formatter를 작성하여 프로그램의 상태를 변경하지 않는다는 것을 기억하는 것이 상당히 중요합니다.
이제 우리는 이 모든 작업을 완료했고 이제 이 모든 것을 얻었습니다. 이제 우리는 어떤 이점을 얻을 수 있습니까? 글쎄, 우리는 그것을 다시 시도 할 수 있습니다.
우리가 간다.
그리고 지금 나는 그것을 다시 본다.
내 물건이 보입니다.
네, 혹시 궁금하시다면 어제 쿠퍼티노는 정말 더웠습니다.
그리고 지금 우리는 이 일을 했지만 우리가 똑똑했고 미리 일을 했기 때문에 한 것입니다.
때때로 나는 뭔가를 디버그하려고 하고 내가 원하는 곳에 내 프로그램을 가지고 있습니다.
재현하기 어려운 버그가 드디어 발생했습니다.
하지만 지금은 데이터를 보기가 정말 어렵습니다.
데이터가 혼란스럽고 복잡합니다.
그리고 이전에 이 작업을 수행하여 이제 훨씬 더 간단한 방법으로 내 데이터를 실제로 볼 수 있기를 바랍니다.
그러나 나는 그렇지 않습니다.
모든 희망이 사라졌습니다.
아니요! 아니, 그렇지 않아! 적합성 및 런타임도 추가할 수 있습니다.
표현식 파서를 통해 이러한 적합성을 추가하고 앱을 디버깅하는 동안 실행할 수 있습니다.
반면에 변경할 수 없습니다.
기존 적합성은 유지됩니다.
당신은 REPL에 있고 실험 중입니다.
당신은 정말로 당신이 무언가를 할 수 있기를 바랍니다.
오, 내가 적합성을 추가할 수 있다면 얼마나 좋을까.
REPL에서도 그렇게 할 수 있습니다.
그리고 물론, 하지만 여러분 모두가 그것을 예상할 것이라고 확신합니다. 놀이터에서도요.
저것 봐! Kate, Sean, 그리고 저에게서 들은 우리가 지난 1년 동안 디버거 분야에서 수행한 많은 작업은 액세스하기가 정말 쉬운지 확인하는 것과 관련이 있는 것 같습니다. 디버깅하는 동안 최대한 많은 정보를 얻으십시오.
Objective-C 런타임에 액세스하면 이전에는 사용할 수 없었던 필드에 대한 더 많은 통찰력을 얻을 수 있습니다.
SDK 모듈은 애플리케이션이 실행되는 운영 환경, 더 많은 유형, 더 많은 기능, 매크로에 대한 전례 없는 수준의 액세스를 제공합니다.
그리고 진행 중인 서식, 진행 중인 서식을 사용하면 전반적으로 적용할 수 있는 매력적인 유형 표현을 만들 수 있습니다.
그들은 플레이그라운드에 적용하고 REPL에 적용하고 디버거에 적용합니다.
물론 더 많은 정보를 원하시면 주저하지 마시고 저희 웹사이트, Swift 언어 문서 또는 개발자 포럼을 방문하세요. 물론 Labs와 저희의 Evangelist인 Stefan은 이메일을 통해서만 연락이 가능합니다.
