Eliminar println () para la versión de lanzamiento iOS Swift

84

Me gustaría ignorar globalmente todas las println()llamadas en mi código Swift si no estoy en una compilación de depuración. No puedo encontrar instrucciones sólidas paso a paso para esto y agradecería orientación. ¿Hay alguna manera de hacer esto a nivel mundial, o necesito rodear cada uno println()con #IF DEBUG/#ENDIFdeclaraciones?

Nate Birkholz
fuente
6
la impresión ya no se imprime en la consola del dispositivo, pero sí en la consola del depurador.
Anish Parajuli 웃
1
A partir de Xcode 8 y swift 3, no veo impresiones en la consola en modo de lanzamiento.
CiNN

Respuestas:

101

La forma más sencilla es poner su propia función global frente a la de Swift println:

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

Cuando sea el momento de detener el registro, simplemente comente el cuerpo de esa función:

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

O puede hacerlo automático usando un condicional:

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

EDITAR En Swift 2.0 printlnse cambia a print. Desafortunadamente, ahora tiene un primer parámetro variadic; esto es genial, pero significa que no puede anularlo fácilmente porque Swift no tiene un operador "splat", por lo que no puede pasar un código variable (solo se puede crear literalmente). Pero puede hacer una versión reducida que funcione si, como suele ser el caso, está imprimiendo solo un valor:

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

En Swift 3, debe suprimir la etiqueta externa del primer parámetro:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    Swift.print(items[0], separator:separator, terminator: terminator)
}
mate
fuente
3
Buena solución, gracias. Me han dicho que en iOS (pero no en OS X), println()no se ejecuta en modo de lanzamiento.
Nate Birkholz
13
@NateBirkholz No, eso es una tontería. (¡Dijo él, después de probar para asegurarse!)
Matt
En swift 2, con la función renombrada para imprimir, ¿podría cambiar la función para que coincida? Además, ¿cómo definiría esto globalmente? Intenté ponerlo fuera de mi clase en AppDelegate y nunca se llama aunque tengo un millón de llamadas print (). Esto es lo que probé: func print (object: Any) {Swift.print (object)}
Charlie
@Charlie Sí, todavía lo estoy usando con printlncambiado a print. La razón por la que no funciona para usted es que su printdefinición no coincide con la de Swift, por lo que no la está anulando. Hay un pequeño problema porque, como se ha comentado muchas veces, Swift no tiene un operador de splat, por lo que no puede pasar la variadic. Pero funciona bien para un elemento, que puede pasar como items[0].
Matt
2
Una advertencia aquí si está insertando estas declaraciones de registro en secciones de código de alto rendimiento: Swift todavía pasará tiempo haciendo interpolación de cadenas y renderizando parámetros para pasar a la función, incluso si no se van a usar. La única forma que veo de eliminar las declaraciones de forma condicional es predicarlas en una bandera. por ejemplo, if (log) {print (..)} en cada ubicación donde se utilizan.
Pat Niemeyer
46

Actualizado para Swift 4.x:

Con Swift 2.0 / 3.0 y Xcode 7/8 ahora fuera de la versión beta, ha habido algunos cambios en la forma en que deshabilita la función de impresión en las versiones de lanzamiento.

Hay algunos puntos importantes mencionados anteriormente por @matt y @Nate Birkholz que aún son válidos.

  1. La println()función ha sido reemplazada porprint()

  2. Para usar la #if DEBUG macro, debe definir el "Compilador rápido - Banderas personalizadas - Otras banderas" para contener el valor-D DEBUG

  3. Recomendaría anular la Swift.print()función en el alcance global para que pueda usar la print()función normalmente en su código, pero eliminará la salida para compilaciones que no sean de depuración. Aquí hay una firma de función que puede agregar en el ámbito global para hacer esto en 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
    }
    

Nota: Hemos configurado el separador predeterminado para que sea un espacio aquí, y el terminador predeterminado para ser una nueva línea. Puede configurar esto de manera diferente en su proyecto si lo desea.

Espero que esto ayude.

Actualizar:

Por lo general, es preferible poner esta función en el ámbito global, de modo que se ubique frente a la printfunción de Swift . Creo que la mejor manera de organizar esto es agregar un archivo de utilidad a su proyecto (como DebugOptions.Swift) donde puede colocar esta función en el ámbito global.

A partir de Swift 3, el ++operador quedará obsoleto. Actualicé el fragmento anterior para reflejar este cambio.

Glavid
fuente
1
Lo siento, pero ¿dónde poner la función?
DàChún
@ User9527 Es probable que desee poner esto en algún lugar del alcance global, para que sea accesible en todo su proyecto. En mis proyectos, agrego un archivo rápido de utilidad (DebugOptions.swift o algo similar) y coloco esta función en el alcance global (es decir, no en una clase incluida).
Glavid
¿Puede confirmar que a partir de la versión actual de Swift-Xcode, la declaración de impresión ya no se enviará a la consola del dispositivo sin necesidad de establecer la depuración -D plana? Al menos eso es lo que he probado hoy.
user523234
1
A partir de Swift 3, se puede obtener un poco más de brevedad agregando un guión bajo al comienzo de la lista de argumentos: "print (_ items ..."
Jonathan Zhan
7
Así que busqué la referencia de la impresión (usada en didFinishLaunching ...) y me indicó la función de impresión original Swift. Juntando eso y el comentario de @ JonathanZhan, ajusté la función para que se vea así y listo, funciona:public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
Jonny
38

El problema con todos estos enfoques, incluido el mío, es que no eliminan la sobrecarga de evaluar los printargumentos. No importa cuál de ellos use, esto será costoso:

print(myExpensiveFunction())

La única solución decente es envolver la llamada de impresión real en compilación condicional (supongamos que DEBUGestá definida solo para compilaciones de depuración):

#if DEBUG
print(myExpensiveFunction())
#endif

Eso, y solo eso, evita que myExpensiveFunctionse llame en una versión de lanzamiento.

Sin embargo, puede retrasar la evaluación un nivel utilizando el cierre automático . Por lo tanto, podría reescribir mi solución (esto es Swift 3) de esta manera:

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

Esto resuelve el problema solo en el caso de que esté imprimiendo solo una cosa, lo que suele ser cierto. Eso es porque item()no se llama en modo de lanzamiento. print(myExpensiveFunction())así deja de ser caro, porque la llamada se envuelve en un cierre sin ser evaluada, y en modo de liberación, no se evaluará en absoluto.

mate
fuente
¿De qué sirve @autoclosure?
Kelin
@matt en su libro, menciona "Una característica importante de la impresión es que se suprime de manera efectiva cuando la aplicación se inicia independientemente de Xcode". ¿alguna cosa?
nombre de usuario oculto
@ hidden-username Sí, suelo dejar mis printdeclaraciones en mi código de envío, pero eso es diferente de lo que trata mi respuesta aquí. La printsalida de una declaración no se envía a la consola en su versión de versión independiente de Xcode, pero aún se evalúa , por lo que sigue siendo útil saber cómo suprimir esa evaluación en caso de que sea costosa o tenga efectos secundarios no deseados.
Matt
@matt oh ok ... Sí, lo entendí mal. Los comentaré. Gracias
nombre de usuario oculto
¿Este enfoque eliminará la cadena impresa del archivo binario? Por ejemplo, si utilicé ese método y en algún lugar de mi aplicación puse "print (" usuario conectado ")" y luego, si alguien intenta realizar ingeniería inversa en mi aplicación, ¿encontrará esta cadena en alguna parte o no estará allí?
Leszek Szary
18

Como se señaló, soy un estudiante y necesito que las cosas se definan un poco más claramente para seguirlas. Después de mucha investigación, la secuencia que tenía que seguir es:

Haga clic en el nombre del proyecto en la parte superior del Navegador de archivos a la izquierda de la ventana del proyecto Xcode. Esta es la línea que tiene el nombre del proyecto, cuántos destinos de compilación hay y la versión del SDK de iOS.

Elija la pestaña Build Settings y desplácese hacia abajo hasta la sección " Swift Compiler - Custom Flags " cerca de la parte inferior. Haga clic en la flecha hacia abajo junto a Otras banderas para expandir la sección.

Haga clic en la línea Debug para seleccionarla. Coloque el cursor del mouse sobre el lado derecho de la línea y haga doble clic. Aparecerá una vista de lista. Haga clic en el botón + en la parte inferior izquierda de la vista de lista para agregar un valor. Se activará un campo de texto.

En el campo de texto, ingrese el texto -D DEBUGy presione Retorno para confirmar la línea.

Agregue un nuevo archivo Swift a su proyecto. Querrá crear una clase personalizada para el archivo, así que ingrese el texto siguiendo las líneas de lo siguiente:

class Log {

  var intFor : Int

  init() {
    intFor = 42
   }

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

Hoy estaba teniendo problemas para que Xcode aceptara la clase, por lo que el init puede ser un poco más pesado de lo necesario.

Ahora deberá hacer referencia a su clase personalizada en cualquier clase en la que desee utilizar la nueva función personalizada en lugar de println()Agregar esto como una propiedad en cada clase aplicable:

   let logFor = Log()

Ahora puede reemplazar cualquier instancia de println()con logFor.DLog(). La salida también incluye el nombre de la función en la que se llamó a la línea.

Tenga en cuenta que dentro de las funciones de clase no podría llamar a la función a menos que hiciera una copia de la función como una función de clase en esa clase, y println()también es un poco más flexible con la entrada, por lo que no podría usar esto en cada instancia en mi código.

Nate Birkholz
fuente
8
No es necesario crear una clase personalizada para el registro de depuración. Es más fácil y práctico utilizar una función global.
Vojtech Vrbka
¿Cuál es el uso de intFor = 42?
Ted
15

Rápido 5

Simplemente cree un nuevo archivo en su proyecto y pegue este código en:

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

La firma de esta función coincide con la de Swift predeterminada, por lo que "sobrescribe" la función en su proyecto. Si es necesario, aún puede acceder al original utilizando Swift.print().

Una vez que haya agregado el código anterior, siga usando print()el como de costumbre y solo se imprimirá en compilaciones de depuración.

Nota: Hacer el forEachpara imprimir cada elemento elimina los molestos paréntesis de matriz alrededor de las declaraciones de impresión que aparecen si simplemente pasa itemsdirectamente a Swift.print().

Para cualquiera que sea relativamente nuevo en Swift, puede que se pregunte qué diablos $0es. Simplemente representa el primer argumento que se pasa al forEachbloque. La forEachdeclaración también podría escribirse así:

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

Por último, si está interesado, la declaración de Swift se printve así:

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

Mi respuesta anterior refleja la implementación exacta de Swift, aunque nunca imprimo más de una cosa ni cambio separadores / terminadores. Pero quién sabe, es posible que desee.

Trev14
fuente
2
dónde declarar esta función, ¿es una extensión o algo como esto? Simplemente no quiero declararlo en cada archivo)
Matrosov Alexander
1
@MatrosovAlexander Puede crear un archivo rápido en cualquier lugar del proyecto de su aplicación e introducir este código. El compilador es lo suficientemente inteligente como para hacerlo accesible globalmente.
Trev14
11

Aquí hay una función que uso, que funciona perfectamente en 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
    }

Aquí hay un ejemplo de la salida que genera:

captura de pantalla de la salida

Explicación:

  • la marca de verificación verde se usa para permitirle ver rápidamente sus mensajes impresos (gLog) en la consola, donde a veces pueden perderse en un mar de otros mensajes

  • el sello de hora / fecha

  • el hilo en el que se está ejecutando; en mi caso, es MainThread (que llamo UI) o no MainThread (que llamo BG, para el hilo de fondo)

  • el nombre del archivo en el que reside el mensaje gLog

  • la función dentro del archivo en el que reside el mensaje gLog

  • el número de línea del mensaje gLog

  • el mensaje de gLog real que le gustaría imprimir

¡Espero que esto sea útil para alguien más!

Gene Loparco
fuente
¿Se puede poner esto en un archivo separado para usarlo en toda la aplicación? Intenté ponerlo en un archivo de clase separado, como método de clase. Pero falla con libMobileGestalt MobileGestaltSupport.m: 153: pid 2574 (Demo) no tiene acceso a sandbox para frZQaeyWLUvLjeuEK43hmg y NO TIENE el título apropiado libMobileGestalt MobileGestalt.c: 550: no tiene acceso a InverseDeviceID (ver <rdar445: // problema ) Mensaje del depurador: terminado debido a un problema de memoria
omarojo
omarojo, lo uso como una función global en toda mi aplicación. No es necesaria ninguna clase. Tengo un archivo llamado utils.swift, que contiene todas mis funciones de utilidad, como esta. Solo necesita asegurarse de importar Foundation, ¿quizás ese es el paso que se ha perdido? Por cierto, para obtener más información sobre cómo declarar sus funciones dentro de las clases, como funciones estáticas dentro de las clases o como funciones globales, consulte esta pregunta y respuestas de SO: stackoverflow.com/questions/30197548/…
Gene Loparco
Sí, lo hice funcionar simplemente creando un nuevo archivo con la función dentro. Por alguna razón, tenerlo como una función de clase bloquearía la aplicación sin un mensaje de depuración claro.
omarojo
Gracias por este hombre, lástima que no lo descubrí antes. Me ahorró muchos dolores de cabeza de depuración.
beowulf
¡Es un placer @beowulf!
Gene Loparco
9

Probado con Swift 2.1 y Xcode 7.1.1

Existe una manera fácil de excluir todas las declaraciones de impresión de las versiones de lanzamiento, una vez que sepa que el compilador de Swift elimina las funciones vacías .

Nota al margen: en la era de Objective-C, había un pre-analizador que podía usarse para eliminar declaraciones NSLog antes de que el compilador se activara, como se describe en mi respuesta aquí . Pero como Swift ya no tiene un analizador previo, este enfoque ya no es válido.

Esto es lo que uso hoy en día como una función de registro avanzada y fácilmente configurable, sin tener que preocuparme por eliminarlo en las versiones de lanzamiento. Además, al configurar diferentes indicadores del compilador, puede modificar la información que se registra según sea necesario.

Puede modificar la función según sea necesario, ¡cualquier sugerencia para mejorarla es bienvenida!

// 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
}

Aquí es donde configura las banderas del compilador:

ingrese la descripción de la imagen aquí

Un ejemplo de salida con todas las banderas encendidas se ve así:

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

El código con log () se ve así:

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

   // Handle the text field's user input through delegate callbacks
   nameTextField.delegate = self
}
Ronny Webers
fuente
¡Buena esa! Lo tomé de aquí e hice AELog y AEConsole eventualmente.
tadija
Esto funciona bien en modo DEBUG. Ahora, he cambiado al modo LIBERAR desde Editar esquema. También muestra la ventana de inicio de sesión de la consola para el modo de lanzamiento. ¿Porque?
Jayprakash Dubey
Para Swift 3.2 en Xcode 9 necesitaba cambiar NSLog para imprimir y llamar usando log (mensaje: "hola"), también tuve que poner las banderas como "-D" "kLOG_ENABLE", con las comillas. Todas las demás actualizaciones rápidas de la versión fueron recogidas por el compilador con correcciones sugeridas.
iCyberPaul
1
Aquí usted dice que "las funciones vacías son eliminadas por el compilador Swift", ¿en qué parte de los documentos encontramos eso? ¿Cómo sabes que es así? @ ronny-webers
zumzum
7

Aún más simple, después de asegurarse de que -D DEBUGesté configurado para la OTHER_SWIFT_FLAGSconfiguración de compilación de depuración:

#if !DEBUG
    func print(_ items: Any..., separator: String = " ", terminator: String = "\n") { }
#endif
Rivera
fuente
Sospecho que esto puede requerir un "dónde", ya que los objetos imprimibles se ajustan a uno de esos protocolos del sistema que se mencionan raramente en los videos para wwdc, y creo que al final de las guías rápidas 1.2 vs 2, olvidé la diferencia si hay es uno con el sistema uno
Stephen J
Hasta ahora, esto funciona con Swift 1.2. No he probado 2.0.
Rivera
6

XCode 8 introdujo algunas configuraciones de compilación nuevas .
En particular, uno al que se Active Compilation Conditionshace referencia hace de manera similar a lo que hizo la configuración de Otras banderas .

"Condiciones de compilación activa" es una nueva configuración de compilación para pasar indicadores de compilación condicional al compilador Swift.

Según XCode 8 (probado en 8.3.2) obtendrá esto por defecto:

ingrese la descripción de la imagen aquí

Entonces, sin ninguna configuración, puede escribir lo siguiente:

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

Le recomiendo encarecidamente que si usa este enfoque de manera extensa, cree una clase / estructura / función que envuelva esta lógica de registro. Es posible que desee ampliar esto más adelante.

Javier Cádiz
fuente
4

Varun Naharia tiene la mejor solución hasta ahora. Combinaría su respuesta con la de Rivera ...

  1. crear una -D DEBUGbandera en las directivas del compilador, construir configuraciones.
  2. luego agregue este código:

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

Este código convertirá todo printen nada para su lanzamiento.

Pato
fuente
3

Swift 4 Xcode 10.0

tal vez podrías usar esto

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

La razón de su uso @autoclosurees que si pasa una función como parámetro de mensaje, la función se llamará solo en modo de depuración, lo que provocará un impacto en el rendimiento.

a diferencia de la Swift.print(_ items: Any..., separator: String = default, terminator: String = default)función, mi solución tiene solo un parámetro, porque en la mayoría de los casos, no pasamos múltiples parámetros ya que la función de impresión solo muestra información en la consola, podemos simplemente convertir los parámetros a String:, "\(param1)"+"\(param2)"¿verdad? espero que te guste mi solución

Jiangshi fresco
fuente
1

También puede usar un punto de interrupción, configurarlo para que continúe después de la evaluación y escribir el mensaje de impresión en el punto de interrupción.

ingrese la descripción de la imagen aquí

7RedBits.com
fuente
0

Podrías definir debug_printlncuyo contenido sería aproximadamente:

#if DEBUG
  println()
#endif
Ian MacDonald
fuente
Gracias, ¿dónde podría definirlo mejor? Soy un estudiante, tengo miedo y agradezco mucho la ayuda, pero necesito un contexto más explícito.
Nate Birkholz
Lo declararía en un archivo de encabezado que importaría a cualquier lugar donde quisiera usarlo.
Ian MacDonald
0

Mi solución es usar este código en AppDelegate antes de la clase

// 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 

}
Varun Naharia
fuente
0

para mi solución lo hago simple

import UIKit

class DLog: NSObject {

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

   }

}

luego para mostrarlo solo llama

_ = DLog(title:"any title", log:Any)
Wibowo Raditya Trilaksmono
fuente
0

Terminé usando esto:

#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

Es bastante compacto, imprime información útil (marca de tiempo, nombre de archivo rápido, línea de código, nombre de función) y al menos en mis pruebas no pude encontrar ninguna cadena registrada en el archivo binario de la aplicación cuando se abrió en el editor hexadecimal.

Leszek Szary
fuente
0

Aún más simple: aproveche el hecho de que las afirmaciones se eliminan de las versiones de lanzamiento y solo desde allí se llaman a la impresión. Esto elimina todas las llamadas de registro (sí, incluso las llamadas a Log.da) ya que están vacías cuando se compilan para su lanzamiento.

Pero también escuché que las impresiones se eliminan para las versiones de lanzamiento, pero no pude encontrarlas por escrito. Entonces, por ahora, estoy usando algo como esto a Logcontinuación. Tengo una versión más carnosa en GitHub con emojis (para legibilidad) y temas de registro (para coherencia):

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)
    }
}

En codigo:

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

Visto en el área de depuración de Xcode solo cuando se ejecuta una compilación de depuración:

13: 36: 15.047 - Esto solo se maneja en una compilación de depuración.

Johan
fuente
0

Mi proyecto se desarrolló en Objective C, pero desde el año pasado comencé a fusionar un nuevo código en Swift, por lo que en Swift la siguiente solución funcionó para mí, agregué ese código en Mi archivo constante de Swift:

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

Esto funciona para mí (agregue esto como una función global en el proyecto)

func print(_ items: Any...) {
    #if DEBUG
        Swift.print(items[0])
    #endif
}
harryngh
fuente