How to Log in Swift: print, NSLog, and Logger

How to Log in Swift: print, NSLog, and Logger

Written by

in

Quick answer: Use print() for quick debugging output in Xcode; it adds a newline unless you change its terminator. println() was removed in Swift 2, so replace it with print(). For structured logs you can inspect in Console, use Logger from the os framework.

Why this happens

Swift code and older examples use several names for writing messages: print, println, NSLog, and, in newer code, Logger. They are not interchangeable in every situation. The right choice depends on whether you need a quick value in Xcode’s debug console or logs that can be filtered and inspected through Apple’s unified logging system.

The biggest source of confusion is println. It existed in Swift 1.x, but Swift 2 combined its behavior with print and removed println. Current Swift’s print adds a line break by default. Old advice saying that print does not end the line describes an earlier version of Swift.

How to fix it

1. Replace println with print

If the compiler reports that println is unavailable, change the call to print:

let settings = ["theme": "dark", "notifications": "on"]
print(settings)

print writes a textual representation to standard output, which you can usually see in Xcode’s debug console while running the app. It works with strings and values that can be represented as text, making it useful for quick checks while developing.

By default, each call ends with a newline. To print without moving to a new line, set terminator to an empty string:

print("Loading", terminator: "")
print("...")

You can also print multiple values in one call. separator controls the text between them, while terminator controls what appears at the end:

print("Page", 2, "of", 5, separator: " ", terminator: "\n")

For most temporary debugging, this is the simplest option. Remove or replace noisy diagnostic prints before shipping, especially if they could expose private data or make the output difficult to read.

2. Use Logger for app logging

For logs that should be searchable and categorized in Apple’s unified logging system, use Logger from the os framework. This is generally a better choice than adding new NSLog calls to modern apps.

import Foundation
import os

let logger = Logger(
    subsystem: Bundle.main.bundleIdentifier ?? "com.example.app",
    category: "network"
)

logger.info("Starting request")

The subsystem identifies your app or component, and category groups related messages. Choose meaningful values so you can narrow the output when inspecting logs in Console. A category such as network, persistence, or authentication can make a busy log stream easier to investigate.

Use the level that matches the message:

logger.debug("Received response")
logger.error("Request failed")

debug is for diagnostic detail; error is for failures that need attention. Other available levels include info, notice, fault, and critical. Logging levels help you distinguish routine activity from problems when viewing the unified log.

Be aware of privacy. Dynamic values in Logger messages are subject to privacy handling and may appear as <private> in logs. Do not mark a value public just to make it visible until you have checked that it cannot contain personal or confidential information. If a value is safe to expose, you can explicitly mark it:

let url = URL(string: "https://example.com")!
logger.debug("Request URL: \(url, privacy: .public)")

If the value might include a user identifier, access token, query data, or other sensitive information, leave it private or avoid logging it. For simple messages, prefer static text that does not include user-provided data.

Logger is available on iOS 14 and later and macOS 11 and later. If your app supports earlier operating systems, check your deployment target and availability requirements before using it directly.

3. Keep NSLog for older code or a specific legacy need

NSLog is an older logging function. It includes timestamp and process information in its output and sends messages through Apple’s system logging facilities, so it can be useful when maintaining existing code that already depends on it.

import Foundation

NSLog("Pi to four decimal places: %.4f", Double.pi)

That example uses a printf-style format string. The format specifier must match the value passed to it; for example, %.4f formats a floating-point number with four digits after the decimal point. A mismatched format and argument can produce incorrect output.

For new structured logging, prefer Logger. It gives you named categories and log levels and works with unified logging tools. NSLog remains available, but it does not provide the same convenient structure for filtering messages by the categories you define.

4. Choose based on where you need to see the message

Use this as a quick guide:

  • Use print to inspect a value during a debugging session in Xcode.
  • Use Logger for categorized messages you want to inspect in the unified logging system, including through Console.
  • Use NSLog when working with existing code that already uses it or when you specifically need its older behavior.
  • Do not use println in current Swift; replace it with print.

None of these calls is a substitute for a deliberate production logging and privacy strategy. Avoid logging credentials, personal data, or full request contents unless you have a clear, safe reason.

How to prevent it

  • Replace old println(...) calls with print(...) when updating Swift code.
  • Remember that print adds a newline by default; set terminator when you need different behavior.
  • Use a consistent Logger subsystem and descriptive categories for app diagnostics.
  • Choose appropriate log levels and keep private values out of logs.
  • Check your deployment target before adopting APIs that require newer OS versions.

FAQ

Does print add a newline in Swift?

Yes. Current Swift’s print adds a line break by default. Pass terminator: "" if you do not want one.

Why does Swift say println is unavailable?

println was removed in Swift 2 when its behavior was combined with print. Replace it with print; use the terminator parameter to control line endings.

Should I use NSLog or Logger in a new app?

Use Logger for categorized, leveled messages intended for Apple’s unified logging system. NSLog can remain in older code, but print is usually sufficient for quick, temporary debugging output.

Sources & credits

Parts of this guide are adapted from content licensed under CC BY-SA 4.0; this article is shared under the same license.