Console в Xcode е инструмент за отстраняване на грешки за iOS разработка, който показва изхода на NSLog, print, os_log и crash логовете на приложението в реално време. Според Apple Unified Logging, от iOS 10 Apple препоръчва използването на os_log вместо NSLog за централизирано събиране на съобщения чрез Unified Logging System. Console обединява изхода на дебъгера и системните съобщения в единен прозорец на Debug Area, достъпен във всеки момент на разработка.
Основни точки
Console — част от Debug Area в Xcode, разположена в долния панел на редактора (View → Debug Area → Activate Console, комбинация Cmd + Shift + Y). Console показва целия текстов изход на работещото приложение: съобщения от NSLog, os_log, print, предупреждения по време на изпълнение (runtime warnings) и автоматични дампове на изключения при срив на приложението.
Console работи както на симулатора, така и на физическото устройство. На симулатора съобщенията пристигат незабавно чрез локален pipe, на устройството — чрез USB връзка със закъснение от 1–3 кадъра. За производствени приложения Console на устройството не е достъпна — разработчикът разчита на Crashlytics или Unified Logging с отдалечено събиране чрез log collect.
За разлика от системното приложение Console.app на Mac, прозорецът Console в Xcode показва само логовете на текущото работещо приложение (с възможност за филтриране). Console.app събира логове на всички процеси на Mac, включително iOS симулатори. Въпреки това, за отстраняване на грешки в iOS приложения, разработчиците използват вградения Console Xcode поради интеграцията с дебъгера LLDB.
Три основни API са налични за iOS разработчика за извеждане в Console: NSLog (остарял), os_log (препоръчителен) и print (само Swift). Всеки има своите характеристики по отношение на производителност, форматиране и съвместимост с Unified Logging System.
NSLog — функция от Foundation, достъпна в Objective-C и Swift. NSLog извежда съобщение с времеви отпечатък, име на процеса и PID. Недостатъци: NSLog записва в системния буфер синхронно, блокирайки текущата нишка по време на запис. При чести извиквания (например в цикъл), NSLog създава забележимо закъснение. Apple не препоръчва NSLog за нови проекти, но той остава съвместим със стар код и библиотеки на трети страни.
os_log — API от os.framework, представен в iOS 10. os_log е асинхронен: съобщението се поставя в опашка и се записва в буфера без блокиране на извикващата нишка. Според WWDC 2016, os_log е 50 пъти по-бърз от NSLog в сценарии с високо натоварване. os_log също поддържа динамично управление: съобщенията от ниво DEBUG се събират само в Debug компилация, в Release се игнорират без загуба на производителност.
print() — най-простият начин за извеждане в Swift. print записва в stdout (стандартен изход), който Xcode пренасочва към Console. print не добавя метаданни (време, ниво), но поддържа stdout буфериране. За бързо отстраняване на грешки print е удобен инструмент, но за постоянно логване отстъпва на os_log по функционалност и контрол.
import os.log
// NSLog — остарял, блокиращ
NSLog("Application started")
// os_log — препоръчителен, асинхронен
let log = OSLog(
subsystem: "com.myapp",
category: "lifecycle"
)
os_log("Application started", log: log)
// print — бърз Swift изход
print("Application started")
Unified Logging System (ULS) — цялостна инфраструктура за логване на Apple, въведена в iOS 10 и macOS Sierra. ULS събира съобщения от всички системни процеси в единно хранилище с възможност за отдалечен достъп чрез инструмента за команден ред log на Mac. Разработчикът използва os_log за запис в ULS и Console за четене.
Всеки OSLog се идентифицира от двойка subsystem (напр. com.myapp.network) и category (напр. http, websocket). Подсистемата е домейн на приложението (едно приложение може да има няколко подсистеми за различни модули). Категорията е компонент в рамките на подсистемата. Комбинацията subsystem + category позволява гъвкаво филтриране на логове в Console и log collect.
| Ниво | OSLogType | Показване в Console | Събиране в Release |
|---|---|---|---|
| Default | .default | Винаги | Да |
| Info | .info | Когато os_log UI е включен | Да |
| Debug | .debug | Само в Debug компилация | Не |
| Error | .error | Винаги с червен етикет | Да |
| Fault | .fault | Винаги с лилав етикет | Да |
Командата log collect на Mac събира архивирани логове от свързано iOS устройство във файл .logarchive. Този файл може да бъде отворен в Console.app на Mac за подробен анализ, включително os_log съобщения, crash логове и системна диагностика. За включване на събирането на устройството е необходимо да активирате Developer Mode и да свържете устройството чрез USB.
Практическа работа с Console включва три основни сценария: активно логване по време на разработка, анализ на crash логове след срив и отдалечена диагностика чрез .logarchive. За всеки сценарий има оптимален набор от инструменти и настройки.
Препоръчва се да създадете отделен OSLog за всеки модул на приложението с нива: debug (подробно отстраняване на грешки), info (ключови преходи на състояние), error (изключения и повреди). В Console Xcode включете филтър по подсистема на вашето приложение, за да изключите системни съобщения, които създават шум и отвличат вниманието от логиката на приложението.
При срив на приложението Xcode автоматично спира изпълнението и показва нишката, на която е настъпил сривът, с пълен stack trace в Console. Първият ред на crash лога съдържа типа на изключението (NSException, EXC_BAD_ACCESS) и причината (reason). Проучете stack trace отдолу нагоре: последният извикан метод е мястото на срива. За криптирани адреси (в Release) е необходима символикация чрез dSYM.
// Пример за модулна конфигурация на OSLog
extension OSLog {
static let uiLifecycle = OSLog(
subsystem: "com.myapp.ui",
category: "lifecycle"
)
static let network = OSLog(
subsystem: "com.myapp.network",
category: "http"
)
static let database = OSLog(
subsystem: "com.myapp.data",
category: "core-data"
)
}
// Използване с нива
os_log("View did load", log: .uiLifecycle, type: .debug)
os_log("HTTP 200 received", log: .network, type: .info)
os_log("Failed to save: \(error.localizedDescription)",
log: .database, type: .error)
Xcode Console поддържа няколко разширени функции, които надхвърлят простото логване. Breakpoint логовете позволяват извеждане на съобщения в Console без спиране на изпълнението, а LLDB командите в Debugger Command дават пълен контрол върху форматирането на изхода.
Можете да настроите breakpoint така, че да извежда съобщение в Console и автоматично да продължи изпълнението. Поставете breakpoint на желания ред, щракнете с десен бутон → Edit Breakpoint → добавете Debugger Command: “po self” или “expr @import UIKit” + Debugger Command: “po self.view”. Отметнете Automatically continue after evaluating. След стартиране breakpoint ще показва резултата от командата в Console при всяко достигане на реда, без да прекъсва нишката.
Console Xcode поддържа изпълнение на произволни LLDB команди по време на спиране на breakpoint. po (print object) показва описанието на обекта, p (print) — примитивни стойности, а expr — изпълнява Swift/ObjC изрази. За форматиран изход използвайте p/CGRectGetWidth. LLDB изходът се показва в Console веднага след достигане на breakpoint.
func processUserData(user: User) {
// Breakpoint тук с Debugger Command:
// po "User name: \(user.name)"
// expr user.age = 30
print("Processing user: \(user.name)")
}
// Пример за персонализирано логване с последователност
func trackMethodCall(
file: String = #file,
function: String = #function
) {
os_log("[\(function)] called",
log: .uiLifecycle, type: .debug)
}
Console Xcode е тясно интегрирана с Instruments — инструмента за профилиране на Xcode. При стартиране на приложението чрез Product → Profile с шаблон Logging, всички os_log съобщения се записват в трасетата на Instruments с времеви отпечатъци. Това позволява едновременно виждане на логове, производителност и системни събития на една времева скала, което е критично за диагностициране на race condition и регресия на производителността.
Често задавани въпроси
NSLog — синхронен, блокира нишката и винаги извежда съобщение. os_log — асинхронен, 50 пъти по-бърз в сценарии с високо натоварване, поддържа категории и динамично изключване на debug нива в Release компилация без загуба на производителност.
Проверете нивото на логване: по подразбиране Console показва само default и нагоре. За преглед на info и debug отворете менюто os_log в Console Xcode и изберете Include Info Messages и Include Debug Messages, също в настройките на схемата (Edit Scheme → Run → Arguments → OS_ACTIVITY_MODE = debug).
Изберете нужните съобщения в Console, копирайте (Cmd + C) и поставете в произволен текстов редактор. За пълен dump използвайте терминална команда: sudo log collect --device --output /tmp/app_logs.logarchive — тя запазва всички логове от iOS устройството в структуриран формат.
os_log от тип .default и .error работят в Release по подразбиране. За .info и .debug в Release трябва да добавите аргумент за стартиране -OSLogPreferencesApp “$(PRODUCT_BUNDLE_IDENTIFIER):debug” в схемата на Xcode. Без този аргумент debug съобщенията не се събират в Release, което спестява ресурси на устройството.
Отворете Window → Organizer → Crashes в Xcode. Органайзерът показва всички crash логове, събрани от устройствата на тестерите, групирани по тип изключение. За символикация е необходим .dSYM файл от компилацията, на която е настъпил сривът — Xcode го намира автоматично, когато архивът е наличен.
Заключение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също