Rimuovi println () per la versione di rilascio iOS Swift


84

Vorrei ignorare globalmente tutte le println()chiamate nel mio codice Swift se non sono in una build di debug. Non riesco a trovare istruzioni dettagliate per questo e apprezzerei una guida. c'è un modo per farlo a livello globale o devo circondare ogni cosa println()con #IF DEBUG/#ENDIFaffermazioni?



6
print non produce più output nella console del dispositivo ma nella console del debugger. Quindi non è necessario rimuovere per la versione di rilascio.
Anish Parajuli 웃

1
A partire da Xcode 8 e swift 3 non vedo stampe nella console in modalità di rilascio.
CiNN

Risposte:


102

Il modo più semplice è mettere la tua funzione globale davanti a quella di Swift println:

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

Quando è il momento di interrompere la registrazione, commenta semplicemente il corpo di quella funzione:

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

Oppure puoi renderlo automatico usando un condizionale:

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

EDIT In Swift 2.0 printlnè cambiato in print. Purtroppo ora ha un primo parametro variadico; questo è interessante, ma significa che non puoi sovrascriverlo facilmente perché Swift non ha un operatore "splat" quindi non puoi passare un variadic nel codice (può essere creato solo letteralmente). Ma puoi creare una versione ridotta che funzioni se, come di solito accade, stai stampando solo un valore:

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

In Swift 3, devi eliminare l'etichetta esterna del primo parametro:

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

3
Bella soluzione, grazie. Mi è stato detto che in iOS (ma non in OS X), println()non viene eseguito in modalità di rilascio.
Nate Birkholz

13
@NateBirkholz No, non ha senso. (Ha detto lui, dopo aver provato per essere sicuri!)
Matt

In swift 2, con la funzione rinominata in print, potresti semplicemente far corrispondere la funzione? Inoltre, come definiresti questo a livello globale? Ho provato a metterlo fuori dalla mia classe in AppDelegate e semplicemente non viene mai chiamato anche se ho un milione di chiamate print (). Ecco cosa ho provato: func print (object: Any) {Swift.print (object)}
Charlie

@Charlie Sì, lo sto ancora usando con printlncambiato in print. Il motivo per cui non funziona è che la tua printdefinizione non corrisponde a quella di Swift, quindi non la sovrascrivi. C'è un piccolo problema perché, come è stato osservato molte volte, Swift non ha un operatore splat, quindi non puoi passare il variadic. Ma funziona bene per un oggetto, che puoi passare come items[0].
matt

2
Un avvertimento qui se stai inserendo queste istruzioni di log in sezioni di codice ad alte prestazioni: Swift continuerà a dedicare tempo all'interpolazione delle stringhe e al rendering dei parametri da passare alla funzione, anche se non verranno utilizzati. L'unico modo che vedo per rimuovere in modo condizionale le dichiarazioni è di predicarle su una bandiera. ad esempio if (log) {print (..)} in ogni posizione in cui vengono utilizzati.
Pat Niemeyer

48

Aggiornato per Swift 4.x:

Con Swift 2.0 / 3.0 e Xcode 7/8 ora fuori beta, sono state apportate alcune modifiche al modo in cui disabiliti la funzione di stampa nelle build di rilascio.

Ci sono alcuni punti importanti menzionati da @matt e @Nate Birkholz sopra che sono ancora validi.

  1. Il println() funzione è stata sostituita daprint()

  2. Per utilizzare #if DEBUG macro devi quindi definire "Swift Compiler - Custom Flags -Other Flags" per contenere il valore-D DEBUG

  3. Consiglierei di sovrascrivere la Swift.print()funzione nell'ambito globale in modo da poter utilizzare la print()funzione normalmente nel codice, ma rimuoverà l'output per build non di debug. Ecco una firma di funzione che puoi aggiungere nell'ambito globale per farlo in 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: abbiamo impostato il separatore predefinito come uno spazio qui e il terminatore predefinito come una nuova riga. Puoi configurarlo in modo diverso nel tuo progetto, se lo desideri.

Spero che sia di aiuto.

Aggiornare:

Di solito è preferibile inserire questa funzione nell'ambito globale, in modo che si trovi di fronte a quella di Swift print funzione . Trovo che il modo migliore per organizzare questo sia aggiungere un file di utilità al tuo progetto (come DebugOptions.Swift) dove puoi inserire questa funzione nell'ambito globale.

A partire da Swift 3, l' ++operatore sarà deprecato. Ho aggiornato lo snippet sopra per riflettere questa modifica.


1
Mi dispiace, ma dove mettere la funzione?
DàChún

@ User9527 È probabile che tu voglia inserirlo da qualche parte nell'ambito globale, in modo che sia accessibile in tutto il progetto. Nei miei progetti, aggiungo un file swift di utilità (DebugOptions.swift o qualcosa di simile) e inserisco questa funzione nell'ambito globale (cioè non in una classe chiusa).
Glavid

Puoi confermare a partire dalla versione corrente di Swift-Xcode, l'istruzione print non verrà più inviata alla console del dispositivo senza la necessità di impostare -D Debug flat? Almeno questo è ciò che ho testato oggi.
user523234

1
A partire da Swift 3, è possibile ottenere un po 'più di brevità aggiungendo un trattino basso all'inizio dell'elenco di argomenti: "print (_ items ..."
Jonathan Zhan

8
Quindi ho cercato il riferimento della stampa (usato in didFinishLaunching ...) e mi ha indirizzato alla funzione di stampa originale Swift. Mettendo insieme questo e il commento di @ JonathanZhan, ho regolato la funzione in modo che assomigliasse a questo e voilà funziona:public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
Jonny

38

Il problema con tutti questi approcci, compreso il mio, è che non rimuovono il sovraccarico della valutazione degli printargomenti. Non importa quale di loro utilizzi, sarà costoso:

print(myExpensiveFunction())

L'unica soluzione decente è racchiudere la chiamata di stampa effettiva nella compilazione condizionale (supponiamo che DEBUGsia definita solo per build di debug):

#if DEBUG
print(myExpensiveFunction())
#endif

Questo, e solo quello, impedisce myExpensiveFunctiondi essere chiamato in una build di rilascio.

Tuttavia, puoi respingere la valutazione di un livello utilizzando la chiusura automatica . Quindi, potresti riscrivere la mia soluzione (questo è Swift 3) in questo modo:

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

Questo risolve il problema solo nel caso in cui si stia stampando solo una cosa, il che di solito è vero. Questo perché item()non viene chiamato in modalità di rilascio. print(myExpensiveFunction())quindi cessa di essere costoso, perché la chiamata è racchiusa in una chiusura senza essere valutata, e in modalità di rilascio, non verrà valutata affatto.


A cosa serve @autoclosure?
kelin

@matt nel tuo libro, dici "Una caratteristica importante della stampa è che viene effettivamente soppressa quando l'app viene avviata indipendentemente da Xcode", significa che possiamo lasciare le nostre dichiarazioni di stampa nelle nostre app inviate in questi giorni, o sto fraintendendo qualcosa?
nome utente nascosto

@ hidden-username Sì, tendo a lasciare le mie printdichiarazioni nel codice di spedizione, ma è diverso da quello di cui tratta la mia risposta. L' printoutput di un'istruzione non viene inviato alla console nella build di rilascio indipendente da Xcode, ma viene comunque valutato , quindi rimane utile sapere come sopprimere tale valutazione nel caso in cui sia costosa o abbia effetti collaterali indesiderati.
matt

@ matt oh ok ... Sì, ho capito male. Li commenterò. Grazie
nome utente nascosto

Questo approccio rimuoverà la stringa stampata dal file binario? Ad esempio, se ho usato quel metodo e da qualche parte nella mia app metto "print (" utente connesso ")" e poi se qualcuno prova a decodificare la mia app troverà questa stringa da qualche parte o non sarà affatto lì?
Leszek Szary

18

Come notato, sono uno studente e ho bisogno che le cose siano definite un po 'più chiaramente da seguire. Dopo molte ricerche, la sequenza che dovevo seguire è:

Fare clic sul nome del progetto nella parte superiore del File Navigator a sinistra della finestra del progetto Xcode. Questa è la riga che ha il nome del progetto, quanti obiettivi di compilazione ci sono e la versione dell'SDK di iOS.

Scegli la scheda Impostazioni build e scorri verso il basso fino a " Swift Compiler - Custom Flags " nella parte inferiore. Fare clic sulla freccia giù accanto ad altri contrassegni per espandere la sezione.

Fare clic sulla riga Debug per selezionarlo. Posiziona il cursore del mouse sul lato destro della linea e fai doppio clic. Apparirà una visualizzazione elenco. Clicca il + pulsante nella parte inferiore sinistra della visualizzazione elenco per aggiungere un valore. Un campo di testo diventerà attivo.

Nel campo di testo, inserisci il testo -D DEBUGe premi Invio per confermare la riga.

Aggiungi un nuovo file Swift al tuo progetto. Hai intenzione di creare una classe personalizzata per il file, quindi inserisci il testo lungo le righe di quanto segue:

class Log {

  var intFor : Int

  init() {
    intFor = 42
   }

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

Oggi ho avuto problemi a far accettare la classe da Xcode, quindi l'init potrebbe essere un po 'più pesante del necessario.

Ora dovrai fare riferimento alla tua classe personalizzata in qualsiasi classe in cui intendi utilizzare la nuova funzione personalizzata al posto di println()Aggiungi come proprietà in ogni classe applicabile:

   let logFor = Log()

Ora puoi sostituire qualsiasi istanza di println() conlogFor.DLog() . L'output include anche il nome della funzione in cui è stata chiamata la riga.

Si noti che all'interno delle funzioni di classe non potrei chiamare la funzione a meno che non abbia creato una copia della funzione come funzione di classe in quella classe, ed println()è anche un po 'più flessibile con l'input, quindi non potrei usarlo in ogni istanza in il mio codice.


8
Non è necessario creare una classe personalizzata per il registro di debug. È più facile e più pratico utilizzare una funzione globale.
Vojtech Vrbka

Qual è l'uso di intFor = 42?
Ted

16

Swift 5

Crea semplicemente un nuovo file nel tuo progetto e incolla questo codice in:

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

Questa firma della funzione corrisponde a quella predefinita di Swift, quindi "sovrascrive" la funzione nel progetto. Se necessario, puoi comunque accedere all'originale utilizzando Swift.print().

Dopo aver aggiunto il codice sopra, continua a usare print()come al solito e verrà stampato solo nelle build di debug.

Nota: la forEachstampa di ciascun elemento elimina le fastidiose parentesi quadre attorno alle istruzioni di stampa che vengono visualizzate se passi itemsdirettamenteSwift.print() .

Per chiunque sia relativamente nuovo a Swift potresti chiederti cosa diavolo $0sia. Rappresenta solo il primo argomento passato nel forEachblocco. La forEachdichiarazione potrebbe anche essere scritta in questo modo:

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

Infine, se sei interessato, la dichiarazione Swift di printassomiglia a questa:

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

La mia risposta sopra rispecchia l'esatta implementazione di Swift, anche se non stampo mai più di una cosa o cambio separatore / terminatore. Ma chi lo sa, potresti volerlo.


2
dove dichiarare questa funzione, è un'estensione o qualcosa di simile? Semplicemente non voglio dichiararlo in ogni file)
Matrosov Alexander

1
@MatrosovAlexander Puoi semplicemente creare un file swift ovunque nel progetto della tua app e inserire questo codice. Il compilatore è abbastanza intelligente da renderlo accessibile a livello globale.
Trev14

11

Ecco una funzione che utilizzo, che funziona perfettamente in 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
    }

Ecco un esempio dell'output che genera:

screenshot dell'output

Spiegazione:

  • il segno di spunta verde èusato per consentirti di vedere rapidamente i tuoi messaggi di stampa (gLog) nella console, dove a volte possono perdersi in un mare di altri messaggi

  • il timbro data / ora

  • il thread su cui viene eseguito - nel mio caso è MainThread (che chiamo UI) o non MainThread (che chiamo BG, per thread in background)

  • il nome del file in cui risiede il messaggio gLog

  • la funzione all'interno del file in cui risiede il messaggio gLog

  • il numero di riga del messaggio gLog

  • il messaggio gLog effettivo che si desidera stampare

Spero che questo sia utile a qualcun altro!


può essere inserito in un file separato da utilizzare in tutta l'app? Ho provato a metterlo in un file di classe separato, come metodo di classe. Ma si blocca con libMobileGestalt MobileGestaltSupport.m: 153: pid 2574 (Demo) non ha accesso sandbox per frZQaeyWLUvLjeuEK43hmg e NON È appropriatamente intitolato libMobileGestalt MobileGestalt.c: 550: nessun accesso a InverseDeviceID (vedi <rdar: // problem / 11744455 ) Messaggio dal debugger: terminato a causa di un problema di memoria
omarojo

omarojo, lo uso come funzione globale nella mia app. Non è necessaria alcuna lezione. Ho un file chiamato utils.swift, che contiene tutte le mie funzioni di utilità, come questa. Devi solo assicurarti di importare Foundation: forse è questo il passaggio che ti sei perso? A proposito, per maggiori informazioni sulla dichiarazione delle tue funzioni all'interno delle classi, come funzioni statiche all'interno delle classi o come funzioni globali, vedi questa domanda e risposte SO: stackoverflow.com/questions/30197548/…
Gene Loparco

Sì, ha funzionato semplicemente creando un nuovo file con la funzione all'interno. Per qualche motivo averlo come funzione di classe bloccherebbe l'app senza un chiaro messaggio di debug.
omarojo

Grazie per quest'uomo, peccato non averlo scoperto prima. Mi ha risparmiato un sacco di mal di testa di debug.
beowulf

Il mio piacere @beowulf!
Gene Loparco

9

Testato con Swift 2.1 e Xcode 7.1.1

C'è un modo semplice per escludere tutte le istruzioni di stampa dalle versioni di rilascio, una volta che sai che le funzioni vuote vengono rimosse dal compilatore Swift .

Nota a margine: nell'era di Objective-C, c'era un pre-parser che poteva essere utilizzato per rimuovere le istruzioni NSLog prima che il compilatore iniziasse, come descritto nella mia risposta qui . Ma poiché Swift non ha più un pre-parser, questo approccio non è più valido.

Ecco cosa utilizzo oggi come funzione di registro avanzata e facilmente configurabile, senza doversi preoccupare di rimuoverla nelle build di rilascio. Inoltre, impostando diversi flag del compilatore, è possibile modificare le informazioni registrate secondo necessità.

Puoi modificare la funzione secondo necessità, qualsiasi suggerimento per migliorarla è il benvenuto!

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

Ecco dove imposti i flag del compilatore:

inserisci qui la descrizione dell'immagine

Un output di esempio con tutti i flag attivi ha il seguente aspetto:

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

Il codice con log () ha questo aspetto:

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

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

Ben fatto! L'ho preso da qui e alla fine ho realizzato AELog e AEConsole .
tadija

Funziona bene in modalità DEBUG. Ora, sono passato alla modalità RELEASE da Modifica schema. Mostra anche la finestra di accesso della console per la modalità di rilascio. Perchè così?
Jayprakash Dubey

Per Swift 3.2 in Xcode 9 avevo bisogno di cambiare NSLog per stampare e chiamare usando log (messaggio: "ciao"), inoltre dovevo mettere i flag come "-D" "kLOG_ENABLE", con le virgolette. Tutti gli altri aggiornamenti rapidi della versione sono stati raccolti dal compilatore con le correzioni suggerite.
iCyberPaul

1
Qui si afferma "le funzioni vuote vengono rimosse dal compilatore Swift", dove lo troviamo nella documentazione? Come fai a sapere che è così? @ ronny-
webers

7

Ancora più semplice, dopo esserti assicurato che -D DEBUGsia impostato per le OTHER_SWIFT_FLAGSimpostazioni di build di debug:

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

Sospetto che ciò possa richiedere un "dove" poiché gli oggetti stampabili sono conformi a uno di quei protocolli di sistema che vedi menzionati raramente nei video per wwdc, e penso che alla fine delle guide rapide 1.2 vs 2, ho dimenticato la differenza se lì è uno con il sistema uno
Stephen J

Finora funziona con Swift 1.2. Non ho provato 2.0.
Rivera

6

XCode 8 ha introdotto alcune nuove impostazioni di build .
In particolare quello a cui si Active Compilation Conditionsfa riferimento fa in modo simile ciò che hanno fatto le impostazioni di Other Flags .

"Condizioni di compilazione attiva" è una nuova impostazione di compilazione per il passaggio di flag di compilazione condizionale al compilatore Swift.

Come per XCode 8 (testato in 8.3.2) otterrai questo per impostazione predefinita:

inserisci qui la descrizione dell'immagine

Quindi senza alcuna configurazione puoi scrivere quanto segue:

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

Ti consiglio vivamente che, se utilizzi questo approccio in modo estensivo, crea una classe / struttura / funzione che racchiuda questa logica di registrazione. Potresti volerlo estendere ulteriormente lungo la strada.


4

Varun Naharia ha finora la soluzione migliore. Combinerei la sua risposta con quella di Rivera ...

  1. creare un -D DEBUGflag sulle direttive del compilatore, costruire le impostazioni.
  2. quindi aggiungi questo codice:

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

Questo codice convertirà tutto printin niente per il rilascio.


3

Swift 4 Xcode 10.0

forse potresti usarlo

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

Il motivo dell'utilizzo @autoclosure è che se si passa una funzione come parametro del messaggio, la funzione verrà chiamata solo in modalità di debug, causando un calo delle prestazioni.

a differenza della Swift.print(_ items: Any..., separator: String = default, terminator: String = default)funzione, la mia soluzione ha un solo parametro, perché nella maggior parte dei casi non passiamo più parametri poiché la funzione di stampa mostra solo le informazioni nella console, possiamo semplicemente convertire i parametri in String:, "\(param1)"+"\(param2)"giusto? spero ti piaccia la mia soluzione


1

È inoltre possibile utilizzare un punto di interruzione, impostarlo per continuare dopo la valutazione e scrivere il messaggio di stampa nel punto di interruzione!

inserisci qui la descrizione dell'immagine


0

Potresti definire il debug_printlncui contenuto sarebbe approssimativamente:

#if DEBUG
  println()
#endif

Grazie, dove potrei definirlo meglio? Sono uno studente, ho paura e apprezzo molto l'aiuto ma ho bisogno di un contesto più esplicito.
Nate Birkholz

Lo dichiareresti in un file di intestazione che importeresti ovunque tu voglia usarlo.
Ian MacDonald

0

La mia soluzione è utilizzare questo codice in AppDelegate prima della lezione

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

per la mia soluzione lo rendo semplice

import UIKit

class DLog: NSObject {

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

   }

}

quindi per mostrarlo basta chiamare

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

0

Ho finito per usare questo:

#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

È abbastanza compatto, stampa alcune informazioni utili (timestamp, nome del file swift, riga di codice, nome della funzione) e almeno nei miei test non sono riuscito a trovare alcuna stringa registrata nel file binario dell'applicazione quando è stato aperto in hex editior.


0

Ancora più semplice: approfitta del fatto che gli assert vengono rimossi dalle build di rilascio e solo da lì chiamano il print. Ciò rimuove tutte le chiamate di registro (sì, anche le chiamate a Log.da) poiché sono vuote durante la compilazione per il rilascio.

Ma ho anche sentito che le stampe vengono rimosse per le build di rilascio, ma non sono riuscito a trovarle per iscritto. Quindi per ora sto usando qualcosa di simile qui Logsotto. Ho una versione più carnosa su GitHub con emoji (per leggibilità) e argomenti di registro (per coerenza):

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

In codice:

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

Visto nell'area di debug di Xcode solo durante l'esecuzione di una build di debug:

13: 36: 15.047 - Questo viene gestito solo in una build di debug.


0

Il mio progetto è stato sviluppato in Objective C, ma dall'anno scorso ho iniziato a unire nuovo codice in Swift, quindi in Swift la soluzione di seguito ha funzionato per me, ho aggiunto quel codice nel file costante My Swift:

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

0

Questo funziona per me (aggiungilo come funzione globale nel progetto)

func print(_ items: Any...) {
    #if DEBUG
        Swift.print(items[0])
    #endif
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.