Swift: print () против println () против NSLog ()

450

В чем разница между print, NSLogи printlnкогда я должен использовать каждый?

Например, в Python, если бы я хотел напечатать словарь, я бы просто print myDict, но теперь у меня есть 2 других варианта. Как и когда я должен использовать каждый?

пользователь
источник
1
возможный дубликат разницы между println и print в Swift
Коннор
2
Что насчет NSLog и печати NSDictionary не дает мне ничего полезного?
Пользователь
Начиная с iOS 10.0 рекомендуется использовать один os_log. Пожалуйста, смотрите мой ответ ниже .
HuaTham
В дополнение к просмотру документации Swift os_log: попробуйте просмотреть полную документацию на странице Objective-C. Это намного более полно .
Мед

Ответы:

758

Несколько отличий:

  1. printпротив println:

    В printфункции вывода сообщений в консоли Xcode при отладке приложений.

    Это printlnвариант этого, который был удален в Swift 2 и больше не используется. Если вы видите старый код, который вы используете println, теперь вы можете смело заменять его на print.

    В Swift 1.x printне добавляли символы новой строки в конце напечатанной строки, тогда как printlnсделали. Но в настоящее время printвсегда добавляется символ новой строки в конце строки, и если вы не хотите, чтобы это делалось, укажите terminatorпараметр "".

  2. NSLog:

    • NSLog медленнее;

    • NSLogдобавляет метку времени и идентификатор к выводу, тогда как printне будет;

    • NSLogоператоры появляются как в консоли устройства, так и в консоли отладчика, а printотображаются только в консоли отладчика.

    • NSLogиспользует printfстроки формата -style, например

      NSLog("%0.4f", CGFloat.pi)

      что даст:

      2017-06-09 11: 57: 55.642328-0700 MyApp [28937: 1751492] 3.1416

  3. Начиная с iOS 10 / macOS 10.12, существует третья альтернатива, os_logчасть системы «унифицированной регистрации» (см. Видеоматериал « Объединенная регистрация и отслеживание активности» WWDC 2016 ).

    • Вы должны импортировать os.logперед использованием os_logфункции:

      import os.log
    • Мол NSLog, os_logбудет выводить сообщения как на консоль отладки Xcode, так и на консоль устройства

    • Теперь вы можете контролировать поля «подсистема» и «категория», доступные в консольном приложении. Например:

      let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "network")
      os_log("url = %@", log: log, url.absoluteString)

      Наблюдая за приложением через внешнее консольное приложение, вы можете не только добавлять эти столбцы в главное представление, но и фильтровать их. Это очень полезно, когда вы хотите отличить ваши сообщения отладки от (а) сообщений, генерируемых другими подсистемами от имени вашего приложения; или (б) сообщения из других категорий или типов.

    • Вы можете задать различные типы регистрации сообщений, либо .info, .debug, .error, .fault(или .default):

      os_log("web service did not respond", type: .error)

      Таким образом, если вы используете внешнее консольное приложение, вы можете выбрать просмотр только сообщений определенных категорий (например, показывать только сообщения отладки, если вы выбрали «Включить отладочные сообщения» в меню «Действие» консоли). Эти настройки также диктуют многие тонкие детали о том, записываются ли данные на диск или нет. Смотрите WWDC видео для более подробной информации.

    • Вы не можете использовать интерполяцию строк при использовании os_log. Например, вы не можете сделать:

      os_log("foo \(url.absoluteString)")

      Вы должны сделать:

      os_log("url = %@", url.absoluteString)
    • Одной из причин вышеуказанного ограничения является поддержка конфиденциальности данных. Примитивные типы данных (например, числа) по умолчанию являются открытыми, а объекты (например, строки) по умолчанию являются закрытыми. В предыдущем примере, где вы зарегистрировали URL-адрес, если приложение было вызвано с самого устройства, а вы просматривали его из консольного приложения Mac, вы увидите:

      url = <личное>

      Если вы хотите увидеть его с внешнего устройства, вам нужно сделать:

      os_log("url = %{public}@", url.absoluteString)
    • Обратите внимание, что NSLogтеперь за кулисами используется единая система уведомлений, но со следующими оговорками:

      • Вы не можете управлять подсистемой, категорией или типом журнала;

      • Он не поддерживает настройки конфиденциальности.

Итог, printдостаточно для простых задач, но NSLogполезен, потому что он содержит информацию о метках времени для вас.

Сила os_logприходит в упадок при отладке приложений iOS, которые должны быть протестированы за пределами Xcode. Например, при тестировании фоновых процессов приложения iOS, таких как фоновая выборка, подключение к отладчику XCode изменяет жизненный цикл приложения . Таким образом, вам часто нужно тестировать на физическом устройстве, запускать приложение с самого устройства, а не запускать приложение из отладчика Xcode. Унифицированное ведение журнала позволяет вам по-прежнему наблюдать за os_logзаявлениями устройства iOS из приложения MacOS Console.

обкрадывать
источник
37
Хорошее резюме! Чтобы добавить еще несколько: вы можете передать NSString в println, но не NSLog; Вы можете добавить аргументы для NSLog, но не println; Интерполяция строк в стиле Swift иногда дает сбой для NSLog, но не println.
Бао Лей
2
интересная заметка об оптимизации компилятора Swift и использовании print () medium.com/ios-os-x-development/…
Carl
@Rob, если я использую print, то появляется ли она в консоли отладчика или нет? Или мы должны использовать debugPrint?
1
Если вы используете print, он появляется в области отладки XCode, как debugPrint. Единственное отличие состоит в том, что в printконечном итоге вызывает descriptionметод объекта и debugPrintвызывает debugDescription, что может быть более многословным, чем description.
Роб
@Honey, эта ветка комментариев помечена как слишком длинная, поэтому я просто хочу напомнить вам, что комментарии не предназначены для расширенного обсуждения или отладки. Если у вас есть вопрос, который можно задать как вопрос, подходящий для формата переполнения стека, то, пожалуйста, задайте его как вопрос, чтобы каждый мог получить пользу от его ответов. Если это не работает как вопрос, то вам нужно принять обсуждение в чате. Оставляйте комментарии только для того, чтобы попросить разъяснений или сделать быстрые наблюдения.
Коди Грей
80

Если вы используете Swift 2 , теперь вы можете использовать только print () для записи чего-либо в вывод.

Apple объединила функции println () и print () в одну.

Обновлено до iOS 9

По умолчанию функция завершает строку, которую печатает, добавляя разрыв строки.

print("Hello Swift")

терминатор

Чтобы напечатать значение без разрыва строки после него, передайте пустую строку в качестве терминатора

print("Hello Swift", terminator: "")

Разделитель

Теперь вы можете использовать разделитель для объединения нескольких элементов

print("Hello", "Swift", 2, separator:" ")

Обе

Или вы можете комбинировать использование таким образом

print("Hello", "Swift", 2, separator:" ", terminator:".")
Хорхе Касариего
источник
5
appendNewlineимеет значение по умолчаниюtrue
Адам
1
В iOS (9.0) вам нужно использовать terminator : "", например,print("...", terminator: "")
Khotu Nam
Утверждение в вашем первом предложении неверно. NSLog () все еще работает, даже в последнем Swift 2.x
Себастьян
62

Более того, Swift 2 имеет debugPrint()CustomDebugStringConvertibleпротокол)!

Не забывайте о том, debugPrint()что работает, print()но наиболее подходит для отладки .

Примеры:

  • Струны
    • print("Hello World!") становится Hello World
    • debugPrint("Hello World!")становится "Hello World"(цитаты!)
  • Изменяется
    • print(1..<6) становится 1..<6
    • debugPrint(1..<6) становится Range(1..<6)

Любой класс может настроить свое представление строки отладки через CustomDebugStringConvertibleпротокол.

Валентин Шергин
источник
2
DebugPrintableпротокол был переименован в CustomDebugStringConvertibleпротокол .
Франклин Ю
Спасибо, Франклин!
Валентин Шергин
Так Свифт descriptionявляется , debugDescriptionкак в Python strявляется repr?
BallpointBen
Да, я так думаю.
Валентин Шергин
39

В дополнение к ответу Роба, начиная с iOS 10.0, Apple представила совершенно новую систему «Unified Logging», которая заменяет существующие системы ведения журналов (включая ASL и Syslog, NSLog), а также превосходит существующие подходы к ведению журналов благодаря своей новой технике, включая сжатие данных журнала и отложенный сбор данных.

От Apple :

Унифицированная система ведения журналов предоставляет единый, эффективный и производительный API для сбора сообщений на всех уровнях системы. Эта унифицированная система централизует хранение данных журнала в памяти и в хранилище данных на диске.

Apple настоятельно рекомендует использовать для os_logпродолжения регистрации все виды сообщений, включая информацию, отладку, сообщения об ошибках, поскольку она значительно улучшила производительность по сравнению с предыдущими системами ведения журналов, а также централизованный сбор данных, позволяющий удобную проверку журналов и действий для разработчиков. На самом деле, новая система, вероятно, настолько мала, что она не вызовет «эффекта наблюдателя», когда ваша ошибка исчезнет, ​​если вы вставите команду регистрации, что будет влиять на время возникновения ошибки.

Выполнение отслеживания активности, теперь часть новой системы единой регистрации

Подробнее об этом вы можете узнать здесь .

Подводя итог: используйте print()для вашей личной отладки для удобства (но сообщение не будет зарегистрировано при развертывании на пользовательских устройствах). Затем используйте Unified Logging ( os_log) как можно больше для всего остального.

HuaTham
источник
5

Есть еще один метод, dump()который также можно использовать для регистрации:

func dump<T>(T, name: String?, indent: Int, maxDepth: Int, maxItems: Int)

Сбрасывает содержимое объекта с помощью его зеркала на стандартный вывод.

Из стандартных функций библиотеки Swift

JAL
источник