Console in Xcode: Key Concepts, Data Output, and Debugging

Author: IT Sectr Published: 2026-05-06 Reading time: 8 min

Console in Xcode is a debugging tool for iOS development that displays NSLog, print, os_log output and app crash logs in real time. According to Apple Unified Logging, starting with iOS 10 Apple recommends using os_log instead of NSLog for centralized message collection via the Unified Logging System. Console combines debugger output and system messages in a single Debug Area window, accessible at any point during development.

Key Takeaways

  • Console Xcode — Debug Area window for viewing NSLog, os_log, print and iOS app crash logs
  • Unified Logging System — Apple’s modern logging system with categories, levels, and disk persistence
  • os_log — recommended logging API with dynamic level configuration support
  • Crash logs appear in Console automatically when the app crashes on a device or simulator
  • Breakpoint logs — output messages to Console without stopping execution via Debugger Command

What is Console in Xcode

Console is part of the Debug Area in Xcode, located in the bottom panel of the editor (View → Debug Area → Activate Console, shortcut Cmd + Shift + Y). Console shows all text output from the running application: messages from NSLog, os_log, print, runtime warnings, and automatic exception dumps when the app crashes.

Console works both in the simulator and on a physical device. In the simulator, messages arrive instantly through a local pipe; on a device, they come via USB connection with a 1–3 frame delay. For production apps, Console on the device is unavailable — developers rely on Crashlytics or Unified Logging with remote collection via log collect.

Unlike the system Console.app on Mac, the Console window in Xcode only shows logs from the currently running application (with filtering capability). Console.app collects logs from all processes on Mac, including iOS simulators. However, for debugging iOS applications, developers use the built-in Xcode Console due to its integration with the LLDB debugger.

Logging APIs: NSLog, os_log and print

Three main APIs are available to iOS developers for Console output: NSLog (deprecated), os_log (recommended), and print (Swift-only). Each has its own characteristics in terms of performance, formatting, and compatibility with the Unified Logging System.

NSLog — Classic Logging

NSLog is a function from Foundation, available in Objective-C and Swift. NSLog outputs a message with a timestamp, process name, and PID. Disadvantages: NSLog writes to the system buffer synchronously, blocking the current thread during writing. With frequent calls (e.g., in a loop), NSLog creates noticeable lag. Apple does not recommend NSLog for new projects, but it remains compatible with legacy code and third-party libraries.

os_log — Modern Standard

os_log is an API from the os.framework, introduced in iOS 10. os_log is asynchronous: the message is queued and written to the buffer without blocking the calling thread. According to WWDC 2016, os_log is 50 times faster than NSLog in high-load scenarios. os_log also supports dynamic control: DEBUG-level messages are only collected in Debug builds, and in Release they are ignored with no overhead.

print() — Swift-only Output

print() is the simplest output method in Swift. print writes to stdout (standard output), which Xcode redirects to Console. print does not add metadata (time, level), but supports stdout buffering. For quick debugging, print is a convenient tool, but for permanent logging it falls short of os_log in functionality and control.

swift
import os.log

// NSLog — deprecated, blocking
NSLog("Application started")

// os_log — recommended, asynchronous
let log = OSLog(
    subsystem: "com.myapp",
    category: "lifecycle"
)
os_log("Application started", log: log)

// print — fast Swift output
print("Application started")

Unified Logging: Categories, Levels and Subsystems

Unified Logging System (ULS) is Apple’s end-to-end logging infrastructure, introduced in iOS 10 and macOS Sierra. ULS collects messages from all system processes into a single storage with remote access capability via the log command-line tool on Mac. Developers use os_log to write to ULS and Console to read.

Subsystems and Categories

Each OSLog is identified by a subsystem (e.g., com.myapp.network) and a category (e.g., http, websocket). The subsystem is the application domain (one app can have multiple subsystems for different modules). The category is a component within the subsystem. The subsystem + category combination allows flexible log filtering in Console and log collect.

OSLog Logging Levels

LevelOSLogTypeConsole DisplayRelease Collection
Default.defaultAlwaysYes
Info.infoWhen os_log UI is enabledYes
Debug.debugDebug build onlyNo
Error.errorAlways with red labelYes
Fault.faultAlways with purple labelYes

log collect — Remote Log Collection

The log collect command on Mac gathers archived logs from a connected iOS device into a .logarchive file. This file can be opened in Console.app on Mac for detailed analysis, including os_log messages, crash logs, and system diagnostics. To enable collection on the device, you need to enable Developer Mode and connect the device via USB.

Working with Console: Step-by-Step Debugging and Crash Log Analysis

Practical work with Console includes three main scenarios: active logging during development, crash log analysis after a crash, and remote diagnostics via .logarchive. Each scenario has an optimal set of tools and settings.

Setting Up Console for Development

It is recommended to create a separate OSLog for each application module with levels: debug (detailed debugging), info (key state transitions), error (exceptions and failures). In Xcode Console, enable filtering by your application’s subsystem to exclude system messages that create noise and distract from the app logic.

Crash Log Analysis

When the app crashes, Xcode automatically stops execution and shows the thread where the crash occurred, with a full stack trace in Console. The first line of the crash log contains the exception type (NSException, EXC_BAD_ACCESS) and the reason. Study the stack trace from bottom to top: the last called method is the crash location. For encrypted addresses (in Release), symbolication via dSYM is required.

swift
// Example of modular OSLog configuration
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"
    )
}

// Usage with levels
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)

Advanced Features: Breakpoint Logs and Custom Formats

Xcode Console supports several advanced features that go beyond simple logging. Breakpoint logs allow you to output messages to Console without stopping execution, and LLDB commands in Debugger Command give you full control over output formatting.

Breakpoint Logs Without Stopping

You can configure a breakpoint to output a message to Console and automatically continue execution. Set a breakpoint on the desired line, right-click → Edit Breakpoint → add Debugger Command: “po self” or “expr @import UIKit” + Debugger Command: “po self.view”. Check Automatically continue after evaluating. After launching, the breakpoint will output the command result to Console each time the line is reached, without interrupting the thread.

LLDB Commands in Console

Xcode Console supports executing arbitrary LLDB commands while stopped at a breakpoint. po (print object) outputs an object description, p (print) outputs primitive values, and expr executes Swift/ObjC expressions. For formatted output, use p/CGRectGetWidth. LLDB output appears in Console immediately after reaching the breakpoint.

swift
func processUserData(user: User) {
    // Breakpoint here with Debugger Command:
    // po "User name: \(user.name)"
    // expr user.age = 30
    print("Processing user: \(user.name)")
}

// Example of custom logging with sequence
func trackMethodCall(
    file: String = #file,
    function: String = #function
) {
    os_log("[\(function)] called",
        log: .uiLifecycle, type: .debug)
}

Integration with Instruments

Xcode Console is closely integrated with Instruments — Xcode’s profiling tool. When running the app via Product → Profile with the Logging template, all os_log messages are recorded in the Instruments trace with timestamps. This allows you to simultaneously view logs, performance, and system events on a single timeline, which is critical for diagnosing race conditions and performance regressions.

Frequently Asked Questions

What is the difference between NSLog and os_log?

NSLog is synchronous, blocks the thread, and always outputs the message. os_log is asynchronous, 50 times faster in high-load scenarios, supports categories, and dynamically disables debug levels in Release builds without performance loss.

Why doesn’t Console show os_log from the app?

Check the logging level: by default, Console only shows default and above. To view info and debug, open the os_log menu in Xcode Console and select Include Info Messages and Include Debug Messages in the scheme settings (Edit Scheme → Run → Arguments → OS_ACTIVITY_MODE = debug).

How to save Console log to a file for sharing?

Select the desired messages in Console, copy (Cmd + C) and paste into any text editor. For a full dump, use the terminal command: sudo log collect --device --output /tmp/app_logs.logarchive — it saves all logs from the iOS device in a structured format.

How to enable os_log in Release build?

os_log types .default and .error work in Release by default. For .info and .debug in Release, you need to add the launch argument -OSLogPreferencesApp “$(PRODUCT_BUNDLE_IDENTIFIER):debug” in the Xcode scheme. Without this argument, debug messages are not collected in Release, saving device resources.

How to find a specific crash log in history?

Open Window → Organizer → Crashes in Xcode. The Organizer shows all crash logs collected from testers’ devices, grouped by exception type. Symbolication requires a .dSYM file from the build where the crash occurred — Xcode automatically finds it if an archive is available.

Summary

  • Console Xcode — built-in tool for viewing NSLog, os_log, print and crash logs in Debug Area
  • os_log — recommended API with asynchronous writing, categories, and Unified Logging System support
  • Unified Logging provides subsystems and categories for modular log organization
  • Breakpoint logs output messages to Console without stopping application execution
  • LLDB commands po, p, expr give full control over console output formatting
  • Crash log analysis starts with the exception in Console and requires symbolication via dSYM for Release
  • Integration with Instruments allows combining logs with profiling on a single timeline

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also