Удалите println () для релизной версии iOS Swift


84

Я хотел бы глобально игнорировать все println()вызовы в моем коде Swift, если я не нахожусь в сборке отладки. Я не могу найти никаких подробных пошаговых инструкций для этого и был бы признателен за руководство. есть способ сделать это глобально, или мне нужно сделать , чтобы окружать каждый println()с #IF DEBUG/#ENDIFутверждениями?



6
print больше не выводится в консоли устройства, но выводится в консоли отладчика .. Следовательно, не нужно удалять для выпуска версии.
Аниш Параджули 웃

1
Начиная с Xcode 8 и Swift 3, я не вижу отпечатков на консоли в режиме выпуска.
CiNN

Ответы:


102

Самый простой способ - поставить свою глобальную функцию перед Swift println:

func println(object: Any) {
    Swift.println(object)
}

Когда пришло время прекратить ведение журнала, просто закомментируйте тело этой функции:

func println(object: Any) {
    // Swift.println(object)
}

Или вы можете сделать это автоматически, используя условное выражение:

func println(object: Any) {
    #if DEBUG
        Swift.println(object)
    #endif
}

РЕДАКТИРОВАТЬ В Swift 2.0 printlnизменено на print. К сожалению, теперь у него есть переменный первый параметр; это круто, но это означает, что вы не можете легко переопределить его, потому что Swift не имеет оператора splat, поэтому вы не можете передавать вариативный код в коде (его можно создать только буквально). Но вы можете сделать сокращенную версию, которая будет работать, если, как обычно бывает, вы печатаете только одно значение:

func print(items: Any..., separator: String = " ", terminator: String = "\n") {
    Swift.print(items[0], separator:separator, terminator: terminator)
}

В Swift 3 вам нужно подавить внешнюю метку первого параметра:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    Swift.print(items[0], separator:separator, terminator: terminator)
}

3
Хорошее решение, спасибо. Мне сказали, что в iOS (но не в OS X) println()не выполняется в режиме выпуска.
Nate Birkholz

13
@NateBirkholz Нет, это чепуха. (Сказал, после тестирования, чтобы убедиться!)
Мэтт

В Swift 2, когда функция переименована в print, не могли бы вы просто совпадать с функцией? Кроме того, как бы вы определили это глобально? Я попытался поместить его за пределы своего класса в AppDelegate, но он просто никогда не вызывается, хотя у меня миллион вызовов print (). Вот что я пробовал: func print (object: Any) {Swift.print (object)}
Чарли,

@Charlie Да, я все еще использую его, но printlnизменил его на print. Причина, по которой это не работает для вас, заключается в том, что ваше printопределение не соответствует Swift, поэтому вы не отменяете его. Есть небольшая проблема, потому что, как уже много раз отмечалось, Swift не имеет оператора splat, поэтому вы не можете передать вариативность. Но он отлично работает для одного элемента, который можно передать как items[0].
Мэтт

2
Одно предостережение, если вы вставляете эти операторы журнала в высокопроизводительные разделы кода: Swift все равно будет тратить время на интерполяцию строк и параметры рендеринга для передачи функции, даже если они не будут использоваться. Единственный способ, который я вижу для действительно условного удаления операторов, - это предикатировать их по флагу. например, if (log) {print (..)} в каждом месте, где они используются.
Пэт Нимейер,

48

Обновлено для Swift 4.x:

Поскольку Swift 2.0 / 3.0 и Xcode 7/8 вышли из стадии бета-тестирования, были внесены некоторые изменения в способ отключения функции печати в сборках выпуска.

Есть некоторые важные моменты, упомянутые выше @matt и @Nate Birkholz, которые все еще актуальны.

  1. println()Функция была замененаprint()

  2. Чтобы использовать #if DEBUG макрос, вы должны определить «Swift Compiler - Custom Flags - Other Flags», чтобы содержать значение-D DEBUG

  3. Я бы порекомендовал переопределить Swift.print()функцию в глобальной области, чтобы вы могли использовать ее print()как обычно в своем коде, но она удалит вывод для сборок без отладки. Вот сигнатура функции, которую вы можете добавить в глобальную область видимости, чтобы сделать это в Swift 2.0 / 3.0:

    func print(items: Any..., separator: String = " ", terminator: String = "\n") {
    
        #if DEBUG
    
        var idx = items.startIndex
        let endIdx = items.endIndex
    
        repeat {
            Swift.print(items[idx], separator: separator, terminator: idx == (endIdx - 1) ? terminator : separator)
            idx += 1
        }
        while idx < endIdx
    
        #endif
    }
    

Примечание. Мы установили здесь разделителем по умолчанию как пробел, а в качестве терминатора по умолчанию - новую строку. Вы можете настроить это по-другому в своем проекте, если хотите.

Надеюсь это поможет.

Обновить:

Обычно предпочтительнее поместить эту функцию в глобальную область видимости, чтобы она располагалась перед printфункцией Swift . Я считаю, что лучший способ организовать это - добавить в проект служебный файл (например, DebugOptions.Swift), в котором вы можете разместить эту функцию в глобальной области видимости.

Начиная с Swift 3, ++оператор устарел. Я обновил приведенный выше фрагмент, чтобы отразить это изменение.


1
Прошу прощения, а куда девать функцию?
DàChún

@ User9527 Скорее всего, вы захотите поместить это где-нибудь в глобальной области видимости, чтобы он был доступен для всего вашего проекта. В своих проектах я добавляю служебный файл swift (DebugOptions.swift или что-то подобное) и помещаю эту функцию в глобальную область видимости (то есть не в закрытый класс).
Glavid 03

Можете ли вы подтвердить, что в текущей версии Swift-Xcode оператор печати больше не будет выводиться на консоль устройства без необходимости устанавливать -D Debug flat? По крайней мере, это то, что я сегодня проверил.
user523234

1
Начиная с Swift 3, можно сделать немного больше краткости, добавив подчеркивание в начале списка аргументов: «print (_ items ...»
Джонатан Жан

8
Итак, я нашел ссылку на печать (использованную в didFinishLaunching ...), и она указала мне на исходную функцию печати Swift. Объединив это и комментарий @JonathanZhan, я настроил функцию так, чтобы она выглядела так, и вуаля, она работает:public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
Джонни,

38

Проблема всех этих подходов, включая мой, заключается в том, что они не устраняют накладные расходы на оценку printаргументов. Независимо от того, какой из них вы используете, это будет дорого:

print(myExpensiveFunction())

Единственное достойное решение - обернуть фактический вызов печати в условную компиляцию (предположим, что DEBUGэто определено только для отладочных сборок):

#if DEBUG
print(myExpensiveFunction())
#endif

Это и только это предотвращает myExpensiveFunctionвызов в сборке выпуска.

Однако вы можете отодвинуть оценку на один уровень, используя автоматическое закрытие . Таким образом, вы можете переписать мое решение (это Swift 3) следующим образом:

func print(_ item: @autoclosure () -> Any, separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    Swift.print(item(), separator: separator, terminator: terminator)
    #endif
}

Это решает проблему только в том случае, если вы печатаете только одну вещь, что обычно верно. Это потому, что item()не вызывается в режиме выпуска. print(myExpensiveFunction())таким образом перестает быть дорогостоящим, потому что вызов завершается закрытием без оценки, а в режиме выпуска он вообще не будет оцениваться.


Какая польза от @autoclosure?
келин

@matt в своей книге вы упоминаете: «Важной особенностью печати является то, что она эффективно подавляется, когда приложение запускается независимо от Xcode», означает ли это, что в наши дни мы можем оставить наши операторы печати в наших отправленных приложениях, или я неправильно понимаю что-то?
hidden-username

@ hidden-username Да, я обычно оставляю свои printутверждения в коде доставки, но это отличается от того, о чем здесь мой ответ. printОператор вывода не отправляется на консоль в вашем Xcode-независимой сборки релиза, но она по - прежнему оценивается , так что остается полезно знать , как подавить эту оценку только в случае , если это дорого или имеет нежелательные побочные эффекты.
matt

@matt ой хорошо ... Да, я неправильно понял. Я их прокомментирую. Спасибо
hidden-username

Удалит ли этот подход напечатанную строку из двоичного файла? Например, если я использовал этот метод и где-то в своем приложении я поставил «print (« пользователь вошел в систему »)», а затем, если кто-то попытается реконструировать мое приложение, найдет ли он эту строку где-то или ее вообще не будет?
Leszek Szary

18

Как уже отмечалось, я студент, и мне нужно более четко определить вещи, чтобы следовать им. После долгих исследований мне нужно было следовать следующей последовательности:

Щелкните имя проекта в верхней части файлового навигатора слева от окна проекта Xcode. Это строка с названием проекта, количеством целей сборки и версией iOS SDK.

Выберите вкладку « Параметры сборки » и прокрутите вниз до раздела « Компилятор Swift - Пользовательские флаги ». Щелкните стрелку вниз рядом с надписью «Другие флаги», чтобы развернуть раздел.

Щелкните строку Debug, чтобы выбрать ее. Наведите курсор мыши на правую часть строки и дважды щелкните. Появится список. Нажмите кнопку + в нижнем левом углу списка, чтобы добавить значение. Текстовое поле станет активным.

В текстовое поле введите текст -D DEBUGи нажмите Return, чтобы зафиксировать строку.

Добавьте в проект новый файл Swift. Вам нужно создать собственный класс для файла, поэтому введите текст в следующих строках:

class Log {

  var intFor : Int

  init() {
    intFor = 42
   }

  func DLog(message: String, function: String = __FUNCTION__) {
    #if DEBUG
      println("\(function): \(message)")
    #endif
  }
}

У меня были проблемы с тем, чтобы класс был принят Xcode сегодня, поэтому init может быть немного тяжелее, чем необходимо.

Теперь вам нужно будет ссылаться на свой настраиваемый класс в любом классе, в котором вы собираетесь использовать новую настраиваемую функцию вместо println()Добавить это как свойство в каждом применимом классе:

   let logFor = Log()

Теперь вы можете заменить все экземпляры println()с logFor.DLog(). Вывод также включает имя функции, в которой была вызвана строка.

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


8
Нет необходимости создавать собственный класс для журнала отладки. Глобальную функцию проще и практичнее использовать.
Войтех Врбка,

Какая польза от intFor = 42?
Тед

16

Swift 5

Просто создайте новый файл в своем проекте и вставьте этот код в:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    items.forEach {
        Swift.print($0, separator: separator, terminator: terminator)        
    }
    #endif
}

Эта сигнатура функции соответствует сигнатуре Swift по умолчанию, поэтому она «перезаписывает» функцию в вашем проекте. При необходимости вы все равно можете получить доступ к оригиналу, используя Swift.print().

После того, как вы добавили приведенный выше код, продолжайте использовать print()как обычно, и он будет печататься только в отладочных сборках.

Примечание: выполнение forEachдля печати каждого элемента избавляет от надоедливых скобок массива вокруг операторов печати, которые появляются, если вы просто переходите itemsпрямо в Swift.print().

Для любого относительно новичка в Swift вы можете задаться вопросом, что это за хрень $0. Он просто представляет первый аргумент, переданный в forEachблок. forEachЗаявление также может быть записано следующим образом:

items.forEach { item in
    Swift.print(item, separator: separator, terminator: terminator)        
}

Наконец, если вам интересно, объявление Swift printвыглядит следующим образом:

public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")

Мой ответ выше отражает точную реализацию Swift - хотя я никогда не печатаю более одного элемента и не меняю разделители / терминаторы. Но кто знает, возможно, вы захотите.


2
где объявить эту функцию, это какое-то расширение или что-то вроде этого? Я просто не хочу декларировать это в каждом файле)
Матросов Александр

1
@MatrosovAlexander Вы можете просто создать быстрый файл в любом месте вашего проекта приложения и вставить этот код. Компилятор достаточно умен, чтобы сделать его глобально доступным.
Trev14

11

Вот функция, которую я использую, которая отлично работает в Swift 3:

func gLog<T>( _ object: @autoclosure() -> T, _ file: String = #file, _ function: String = #function, _ line: Int = #line)
    {
    #if DEBUG
        let value = object()
        let stringRepresentation: String

        if let value = value as? CustomDebugStringConvertible
            {
            stringRepresentation = value.debugDescription
            }
        else if let value = value as? CustomStringConvertible
            {
            stringRepresentation = value.description
            }
        else
            {
            fatalError("gLog only works for values that conform to CustomDebugStringConvertible or CustomStringConvertible")
            }

        let fileURL = NSURL(string: file)?.lastPathComponent ?? "Unknown file"
        let queue = Thread.isMainThread ? "UI" : "BG"
    let gFormatter = DateFormatter()
    gFormatter.dateFormat = "HH:mm:ss:SSS"
        let timestamp = gFormatter.string(from: Date())

        print("✅ \(timestamp) {\(queue)} \(fileURL) > \(function)[\(line)]: " + stringRepresentation + "\n")
    #endif
    }

Вот пример вывода, который он генерирует:

скриншот вывода

Пояснение:

  • зеленая галочка используется для того, чтобы вы могли быстро увидеть свои сообщения печати (gLog) в консоли, где они могут иногда теряться в море других сообщений

  • отметка времени / даты

  • поток, в котором он выполняется - в моем случае это либо MainThread (который я называю UI), либо не MainThread (который я называю BG для фонового потока)

  • имя файла, в котором находится сообщение gLog

  • функция в файле, в котором находится сообщение gLog

  • номер строки сообщения gLog

  • фактическое сообщение gLog, которое вы хотите распечатать

Надеюсь, это будет полезно кому-то еще!


можно ли поместить это в отдельный файл для использования во всем приложении? Я пробовал поместить его в отдельный файл класса, как метод класса. Но он вылетает из-за libMobileGestalt MobileGestaltSupport.m: 153: pid 2574 (Demo) не имеет доступа к песочнице для frZQaeyWLUvLjeuEK43hmg и НЕ имеет подходящего названия libMobileGestalt MobileGestalt.c: 550: нет доступа к InverseDeviceID45: // проблема ) Сообщение от отладчика:
Прервано

omarojo, я использую это как глобальную функцию во всем своем приложении. Класс не нужен. У меня есть файл utils.swift, содержащий все мои служебные функции, такие как эта. Вам просто нужно обязательно импортировать Foundation - возможно, вы пропустили этот шаг? Кстати, для получения дополнительной информации об объявлении ваших функций внутри классов, как статических функций внутри классов или как глобальных функций, см. Этот вопрос и ответы SO: stackoverflow.com/questions/30197548/…
Джин Лопарко

Да, он заработал, просто создав новый файл с функцией внутри. По какой-то причине использование ее в качестве функции класса приведет к сбою приложения без четкого сообщения отладки.
omarojo

Спасибо этому человеку, жаль, что я не обнаружил этого раньше. Избавил меня от головной боли отладки.
Beowulf

С удовольствием @beowulf!
Джин Лопарко 01

9

Протестировано с Swift 2.1 и Xcode 7.1.1

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

Боковое примечание: в эпоху Objective-C существовал предварительный синтаксический анализатор, который можно было использовать для удаления операторов NSLog до запуска компилятора, как описано в моем ответе здесь . Но поскольку в Swift больше нет препарсера, этот подход больше не работает.

Вот то, что я использую сегодня как расширенную и легко настраиваемую функцию журнала, не беспокоясь об ее удалении в сборках выпуска. Также, устанавливая различные флаги компилятора, вы можете настроить информацию, которая регистрируется по мере необходимости.

Вы можете настроить функцию по мере необходимости, любые предложения по ее улучшению приветствуются!

// Gobal log() function
//
// note that empty functions are removed by the Swift compiler -> use #if $endif to enclose all the code inside the log()
// these log() statements therefore do not need to be removed in the release build !
//
// to enable logging
//
// Project -> Build Settings -> Swift Compiler - Custom flags -> Other Swift flags -> Debug
// add one of these 3 possible combinations :
//
//      -D kLOG_ENABLE
//      -D kLOG_ENABLE -D kLOG_DETAILS
//      -D kLOG_ENABLE -D kLOG_DETAILS -D kLOG_THREADS
//
// you can just call log() anywhere in the code, or add a message like log("hello")
//
func log(message: String = "", filePath: String = #file, line: Int = #line, function: String = #function) {
            #if kLOG_ENABLE

            #if kLOG_DETAILS

            var threadName = ""
            #if kLOG_THREADS
                threadName = NSThread.currentThread().isMainThread ? "MAIN THREAD" : (NSThread.currentThread().name ?? "UNKNOWN THREAD")
                threadName = "[" + threadName + "] "
            #endif

            let fileName = NSURL(fileURLWithPath: filePath).URLByDeletingPathExtension?.lastPathComponent ?? "???"

            var msg = ""
            if message != "" {
                msg = " - \(message)"
            }

            NSLog("-- " + threadName + fileName + "(\(line))" + " -> " + function + msg)
        #else
            NSLog(message)
        #endif
    #endif
}

Здесь вы устанавливаете флаги компилятора:

введите описание изображения здесь

Пример вывода со всеми включенными флагами выглядит так:

   2016-01-13 23:48:38.026 FoodTracker[48735:4147607] -- [MAIN THREAD] ViewController(19) -> viewDidLoad() - hello

Код с log () выглядит так:

    override func viewDidLoad() { log("hello")
    super.viewDidLoad()

   // Handle the text field's user input through delegate callbacks
   nameTextField.delegate = self
}

Хороший! Я взял его отсюда и в конце концов сделал AELog и AEConsole .
tadija

Это нормально работает в режиме DEBUG. Теперь я перешел в режим RELEASE из Edit Scheme. Он также показывает журнал в окне консоли для режима выпуска. Почему так?
Джайпракаш Дубей

Для Swift 3.2 в Xcode 9 мне нужно было изменить NSLog для печати и вызова с использованием журнала (сообщение: "привет"), также мне пришлось поставить флаги как "-D" "kLOG_ENABLE" с кавычками. Все остальные быстрые обновления версий были подхвачены компилятором с предложенными исправлениями.
iCyberPaul 06

1
Здесь вы утверждаете, что "пустые функции удаляются компилятором Swift", где в документации мы это находим? Откуда вы знаете, что это так? @ ronny-webers
zumzum 02

7

Еще проще, убедившись, что -D DEBUGустановлены OTHER_SWIFT_FLAGSнастройки сборки отладки:

#if !DEBUG
    func print(_ items: Any..., separator: String = " ", terminator: String = "\n") { }
#endif

Я подозреваю, что для этого может потребоваться «где», поскольку печатаемые объекты соответствуют одному из тех системных протоколов, которые вы редко упоминаете в видеороликах для wwdc, и я думаю, что в конце быстрых руководств 1.2 vs 2, я забыл разницу, если есть один с системным
Стивен Дж

Пока это работает со Swift 1.2. Не пробовал 2.0.
Ривера

6

XCode 8 представил несколько новых настроек сборки .
В частности, упомянутый Active Compilation Conditionsделает то же самое, что и настройки Other Flags .

«Условия активной компиляции» - это новый параметр сборки для передачи флагов условной компиляции компилятору Swift.

Согласно XCode 8 (проверено в 8.3.2) вы получите это по умолчанию:

введите описание изображения здесь

Итак, без какой-либо конфигурации вы можете написать следующее:

#if DEBUG
    print("⚠️ Something weird happened")
#endif

Я настоятельно рекомендую вам, если вы широко используете этот подход, создать класс / структуру / функцию, которая обертывает эту логику ведения журнала. Возможно, вы захотите продлить это дальше по дороге.


4

Пока что у Варуна Нахарии есть лучшее решение. Я бы совмещал его ответ с ответом Риверы ...

  1. создать -D DEBUGфлаг на директивы компилятора, настройки сборки.
  2. затем добавьте этот код:

    #if !DEBUG
     public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    }
    #endif
    

Этот код преобразует все printв ничто для выпуска.


3

Swift 4 Xcode 10.0

может ты мог бы использовать это

func dPrint(_ message: @autoclosure () -> Any) {
    #if DEBUG
    print(message())
    #endif
}

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

в отличие от Swift.print(_ items: Any..., separator: String = default, terminator: String = default)функции, у моего решения только один параметр, потому что в большинстве случаев мы не передаем несколько параметров, так как функция печати показывает информацию только в консоли, мы можем просто преобразовать параметры в String:, "\(param1)"+"\(param2)"верно? надеюсь, тебе нравится мое решение


1

Вы также можете использовать точку останова, установить ее для продолжения после оценки и написать сообщение печати в точке останова!

введите описание изображения здесь


0

Вы можете определить, debug_printlnчье содержимое будет примерно таким:

#if DEBUG
  println()
#endif

Спасибо, где мне лучше всего это определить? Я студент, боюсь и очень ценю помощь, но мне нужен более подробный контекст.
Nate Birkholz

Вы должны объявить его в заголовочном файле, который вы будете импортировать в любое место, где хотите его использовать.
Ian MacDonald

0

Мое решение - использовать этот код в AppDelegate перед классом

// Disable console log in live app
#if !arch(x86_64) && !arch(i386)
    public func debugPrint(items: Any..., separator: String = " ", terminator: String = "\n") {

    }
    public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {

    }
#endif

class AppDelegate: UIResponder, UIApplicationDelegate {
// App Delegate Code 

}

0

для своего решения я делаю это просто

import UIKit

class DLog: NSObject {

   init(title:String, log:Any) {
       #if DEBUG
           print(title, log)
       #endif

   }

}

затем, чтобы показать это, просто позвоните

_ = DLog(title:"any title", log:Any)

0

В итоге я использовал это:

#if DEBUG
func dLog(_ item: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, _ line: Int = #line) {
    print("\(Date()) [\((file as NSString).lastPathComponent):\(line) \(function)] \(item())")
}
#else
func dLog(_ item: @autoclosure () -> Any) {}
#endif

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


0

Еще проще: воспользуйтесь тем, что утверждения удаляются из сборок выпуска и только оттуда вызывают печать. Это удаляет все вызовы журнала (да, даже вызовы Log.da), поскольку они пусты при сборке для выпуска.

Но я также слышал, что отпечатки удаляются для выпускных сборок, но не смог найти это в письменной форме. Итак, сейчас я использую что-то вроде этого Logниже. У меня есть более содержательная версия на GitHub с эмодзи (для удобства чтения) и темами журнала (для согласованности):

https://github.com/Gatada/JBits/blob/master/Project/Utility/Log.swift

public enum Log {

    /// A date formatter used to create the timestamp in the log.
    ///
    /// This formatter is only created if it is actually used, reducing the
    /// overhead to zero.
    static var formatter: DateFormatter?

    // MARK: - API

    /// Call to print message in debug area.
    ///
    /// Asserts are removed in release builds, which make
    /// the function body empty, which caused all calls to
    /// be removed as well.
    ///
    /// Result is zero overhead for release builds.
    public static func da(_ message: String) {
        assert(debugAreaPrint(message))
    }

    // MARK: - Helpers

    /// The function that actually does the printing. It returns `true` to
    /// prevent the assert from kicking in on debug builds.
    private static func debugAreaPrint(_ message: String) -> Bool {
        print("\(timestamp) - \(message)")
        return true
    }

    /// Creates a timestamp used as part of the temporary logging in the debug area.
    static private var timestamp: String {

        if formatter == nil {
            formatter = DateFormatter()
            formatter!.dateFormat = "HH:mm:ss.SSS"
        }

        let date = Date()
        return formatter!.string(from: date)
    }
}

В коде:

Log.da("This is only handled in a debug build.")

Видно в области отладки Xcode только при запуске отладочной сборки:

13: 36: 15.047 - Это обрабатывается только в отладочной сборке.


0

Мой проект был разработан на Objective C, но с прошлого года я начал объединять новый код в Swift, поэтому в Swift ниже решение сработало для меня, я добавил этот код в файл констант My Swift:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    #if DEBUG
    items.forEach {
        Swift.print($0, separator: separator, terminator: terminator)
    }
    #endif
}

0

Это работает для меня (добавьте это как глобальную функцию в проект)

func print(_ items: Any...) {
    #if DEBUG
        Swift.print(items[0])
    #endif
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.