2014-06-04 12 views
42

Sto tentando di riscrivere la mia classe di registrazione e vorrei sapere come sostituire PRETTY_FUNCTION o NSStringFromSelector (_cmd) in un file rapido per tracciare le chiamate al metodo?Registrazione firma del metodo utilizzando swift

+0

Qui è una libreria di registrazione si potrebbe verificare https://github.com/goktugyil/QorumLogs – Thellimist

+0

Per coloro che cercano di implementare funzionalità di registrazione nel loro App o quadro: 'Evergreen' è modellata dopo l'eccellente modulo 'logging' di Python con livelli di registro regolabili e tutto ciò che ci si aspetta da un framework di registrazione: https://github.com/viwid/Evergreen Si basa su una gerarchia di logger che consente anche di regolare la verbosità delle parti del tuo software, ad es abbassare il livello di registro per la parte che si sta attualmente eseguendo il debug. Ciò offre inoltre agli utenti del tuo framework l'opportunità di configurare la verbosità della tua registrazione. – knl

risposta

49

Partenza una nuova libreria che ho appena pubblicato: https://github.com/DaveWoodCom/XCGLogger

Si tratta di una libreria di registrazione di debug per Swift.

La chiave per poter utilizzare i macro #function è impostarli come valori predefiniti per la funzione di registrazione. Il compilatore li riempirà usando i valori attesi.

func log(logMessage: String, functionName: String = #function) { 
    print("\(functionName): \(logMessage)") 
} 

Poi basta chiamare:

log("my message") 

E funziona come previsto dando qualcosa di simile:

whateverFunction(): my message 

Maggiori informazioni su come funziona: http://www.cerebralgardens.com/blog/entry/2014/06/09/the-first-essential-swift-3rd-party-library-to-include-in-your-project

+0

Il bug '__FUNCTION__' è decisamente aggravante, ha confermato che lo vedo nella Beta 1. Fornisco un aggiornamento se lo vedo corretto nelle successive beta. – Joe

+0

Ho una soluzione alternativa in https://github.com/DaveWoodCom/XCGLogger che si occupa del bug '' '__FUNCTION__'''. Dal momento che il bug aggiunge sempre le informazioni sulla funzione alla fine ogni volta che viene chiamato, se lo chiami sempre due volte e usi solo la parte aggiunta, sei a posto. –

+0

@DaveWood, il bug si verifica ancora in Beta3, la soluzione alternativa è ancora necessaria. –

77

letterali speciali in rapida sono i seguenti (dal [la guida rapida]

#fileString Il nome del file in cui appare.

#lineInt Il numero di linee su cui compare.

#columnInt Il numero di colonna nella quale inizia.

#functionStringa Il nome della dichiarazione in cui appare.


Prima di Swift 2.2b4, questi erano

(https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html)):

__FILE__String Il nome del file in cui appare.

__LINE__Int Il numero di riga su cui viene visualizzato.

__COLUMN__Int Il numero di colonna in cui inizia.

__FUNCTION__Stringa Il nome della dichiarazione in cui viene visualizzato.

È possibile utilizzare questi nelle dichiarazioni di registrazione in questo modo:

println("error occurred on line \(__LINE__) in function \(__FUNCTION__)")

+1

Grazie, credo di aver saltato la pistola iniziando dopo aver terminato solo la sezione guida. Ciò che mi dà fastidio è che __FUNCTION__ non include la classe e devo tagliare il percorso del file e mantenere solo il nome del modulo e il nome del file quando si utilizza __FILE__ [/Users/joe.xxxx/Documents/Experimental/Logger/Logger/ViewController .swift]. –

2

Questo otterrà la classe e il nome della funzione in una volta sola:

var name = NSStringFromClass(self.classForCoder) + "." + __FUNCTION__ 
+0

forse 'self.dynamicType' invece di' self.classForCoder' sarebbe semplice? – hideya

4

Prova questo:

class Log { 
    class func msg(message: String, 
     functionName: String = __FUNCTION__, fileNameWithPath: String = __FILE__, lineNumber: Int = __LINE__) { 
     // In the default arguments to this function: 
     // 1) If I use a String type, the macros (e.g., __LINE__) don't expand at run time. 
     // "\(__FUNCTION__)\(__FILE__)\(__LINE__)" 
     // 2) A tuple type, like, 
     // typealias SMLogFuncDetails = (String, String, Int) 
     // SMLogFuncDetails = (__FUNCTION__, __FILE__, __LINE__) 
     // doesn't work either. 
     // 3) This String = __FUNCTION__ + __FILE__ 
     // also doesn't work. 

     var fileNameWithoutPath = fileNameWithPath.lastPathComponent 

#if DEBUG 
     let output = "\(NSDate()): \(message) [\(functionName) in \(fileNameWithoutPath), line \(lineNumber)]" 
     println(output) 
#endif 
    } 
} 

registro utilizzando:

let x = 100 
Log.msg("My output message \(x)") 
4

Ecco quello che ho usato in: https://github.com/goktugyil/QorumLogs
E 'come XCGLogger ma meglio.

func myLog<T>(object: T, _ file: String = __FILE__, _ function: String = __FUNCTION__, _ line: Int = __LINE__) { 
    let info = "\(file).\(function)[\(line)]:\(object)" 
    print(info) 
} 
7

userei qualcosa di simile:

func Log(message: String = "", _ path: String = __FILE__, _ function: String = __FUNCTION__) { 
    let file = path.componentsSeparatedByString("/").last!.componentsSeparatedByString(".").first! // Sorry 
    NSLog("\(file).\(function): \(message)") 
} 

miglioramenti rispetto alle precedenti risposte:

  • Usa NSLog, non stampa/println
  • Vuol Non utilizzare lastPathComponent quali è non più disponibile su stringhe
  • Il messaggio di registro è opzionale
2

Questo stamperà solo in modalità debug:

func debugLog(text: String, fileName: String = __FILE__, function: String = __FUNCTION__, line: Int = __LINE__) { 
    debugPrint("[\((fileName as NSString).lastPathComponent), in \(function)() at line: \(line)]: \(text)") 
} 

Risultato:

"[Book.swift, in addPage() at line: 33]: Page added with success" 
3

Come di Swift 2.2, è possibile specificare utilizzando Literal Expressions, come descritto alla Swift Programming Language guide.

Quindi, se si ha un Logger struct che aveva una funzione che ha registrato in cui l'errore è accaduto, allora si dovrebbe chiamare in questo modo:

Logger().log(message, fileName: #file, functionName: #function, atLine: #line)

0

Swift 3 supporto oggetto DebugLog con la data, il nome della funzione, il nome del file, il numero di riga:

public func debugLog(object: Any, functionName: String = #function, fileName: String = #file, lineNumber: Int = #line) { 
    let className = (fileName as NSString).lastPathComponent 
    print("\(NSDate()): <\(className)> \(functionName) [#\(lineNumber)]| \(object)\n") 
} 
4

Per Swift 3 e superiori:

print("\(#function)") 
0

C'è una nuova libreria che ho pubblicato: Printer.

Ha molte funzioni che consentono di accedere in diversi modi.

Per registrare un messaggio di successo:

Printer.log.success(details: "This is a Success message.") 

uscita:

Printer ➞ [✅ Success] [⌚04-27-2017 10:53:28] ➞ ✹✹This is a Success message.✹✹ 
[Trace] ➞ ViewController.swift ➞ viewDidLoad() #58 

responsabilità: Questa libreria è stata creata da me.

1

questo sembra funzionare bene in rapida 3,1

print("File: \((#file as NSString).lastPathComponent) Func: \(#function) Line: \(#line)") 
0

Ecco il mio prendere su di esso.

func Log<T>(_ object: Shit, _ file: String = #file, _ function: String = #function, _ line: Int = #line) { 

var filename = (file as NSString).lastPathComponent 
filename = filename.components(separatedBy: ".")[0] 

let currentDate = Date() 
let df = DateFormatter() 
df.dateFormat = "HH:mm:ss.SSS" 

print("┌──────────────┬───────────────────────────────────────────────────────────────") 
print("│ \(df.string(from: currentDate)) │ \(filename).\(function) (\(line))") 
print("└──────────────┴───────────────────────────────────────────────────────────────") 
print(" \(object)\n")} 

Spero che vi piaccia.

enter image description here

0
func Log<T>(_ object: T, fileName: String = #file, function: String = #function, line: Int = #line) { 
    NSLog("\((fileName as NSString).lastPathComponent), in \(function) at line: \(line): \(object)") 
} 
+0

Si prega di aggiungere una spiegazione della risposta – brimstone

+0

Ho preso un po 'di tutto da ciascuna risposta qui sotto. Ad esempio invece di stringa è un oggetto e non è necessario inserire l'etichetta dell'argomento in modo che Log (oggetto) e Log ("test") funzionino – hariszaman