Di Objective C Anda bisa mencatat metode yang dipanggil menggunakan:
NSLog(@"%s", __PRETTY_FUNCTION__)
Biasanya ini digunakan dari makro logging.
Meskipun Swift tidak mendukung makro (menurut saya), saya tetap ingin menggunakan pernyataan log umum yang menyertakan nama fungsi yang dipanggil. Apakah itu mungkin di Swift?
Pembaruan: Sekarang saya menggunakan fungsi global untuk logging yang dapat ditemukan di sini: https://github.com/evermeer/Stuff#print Dan yang dapat Anda instal menggunakan:
pod 'Stuff/Print'
Ini kodenya:
public class Stuff {
public enum logLevel: Int {
case info = 1
case debug = 2
case warn = 3
case error = 4
case fatal = 5
case none = 6
public func description() -> String {
switch self {
case .info:
return "❓"
case .debug:
return "✳️"
case .warn:
return "⚠️"
case .error:
return "🚫"
case .fatal:
return "🆘"
case .none:
return ""
}
}
}
public static var minimumLogLevel: logLevel = .info
public static func print<T>(_ object: T, _ level: logLevel = .debug, filename: String = #file, line: Int = #line, funcname: String = #function) {
if level.rawValue >= Stuff.minimumLogLevel.rawValue {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy HH:mm:ss:SSS"
let process = ProcessInfo.processInfo
let threadId = "?"
let file = URL(string: filename)?.lastPathComponent ?? ""
Swift.print("\n\(level.description()) .\(level) ⏱ \(dateFormatter.string(from: Foundation.Date())) 📱 \(process.processName) [\(process.processIdentifier):\(threadId)] 📂 \(file)(\(line)) ⚙️ \(funcname) ➡️\r\t\(object)")
}
}
}
Yang bisa Anda gunakan seperti ini:
Stuff.print("Just as the standard print but now with detailed information")
Stuff.print("Now it's a warning", .warn)
Stuff.print("Or even an error", .error)
Stuff.minimumLogLevel = .error
Stuff.print("Now you won't see normal log output")
Stuff.print("Only errors are shown", .error)
Stuff.minimumLogLevel = .none
Stuff.print("Or if it's disabled you won't see any log", .error)
Yang akan menghasilkan:
✳️ .debug ⏱ 02/13/2017 09:52:51:852 📱 xctest [18960:?] 📂 PrintStuffTests.swift(15) ⚙️ testExample() ➡️
Just as the standard print but now with detailed information
⚠️ .warn ⏱ 02/13/2017 09:52:51:855 📱 xctest [18960:?] 📂 PrintStuffTests.swift(16) ⚙️ testExample() ➡️
Now it's a warning
🚫 .error ⏱ 02/13/2017 09:52:51:855 📱 xctest [18960:?] 📂 PrintStuffTests.swift(17) ⚙️ testExample() ➡️
Or even an error
🚫 .error ⏱ 02/13/2017 09:52:51:855 📱 xctest [18960:?] 📂 PrintStuffTests.swift(21) ⚙️ testExample() ➡️
Only errors are shown
NSLog("Running %@ : %@",NSStringFromClass(self.dynamicType),__FUNCTION__)
Jawaban:
Swift memiliki
#file
,#function
,#line
dan#column
. Dari Bahasa Pemrograman Swift :#file
- String - Nama file di mana file itu muncul.#line
- Int - Nomor baris yang muncul.#column
- Int - Nomor kolom di mana itu dimulai.#function
- String - Nama deklarasi di mana ia muncul.sumber
__PRETTY_FUNCTION__
, yang tidak mudah dibuat dari opsi yang diberikan. (Apakah ada__CLASS__
? Jika demikian, itu akan membantu.)Mulai dari Swift 2.2 kita harus menggunakan:
Dari The Swift Programming Language (Swift 3.1) di halaman 894.
func specialLiterals() { print("#file literal from file: \(#file)") print("#function literal from function: \(#function)") print("#line: \(#line) -> #column: \(#column)") } // Output: // #file literal from file: My.playground // #function literal from function: specialLiterals() // #line: 10 -> #column: 42
sumber
Swift 4
Inilah pendekatan saya:
func pretty_function(_ file: String = #file, function: String = #function, line: Int = #line) { let fileString: NSString = NSString(string: file) if Thread.isMainThread { print("file:\(fileString.lastPathComponent) function:\(function) line:\(line) [M]") } else { print("file:\(fileString.lastPathComponent) function:\(function) line:\(line) [T]") } }
Jadikan ini fungsi global dan panggil saja
Bonus: Anda akan melihat utas dijalankan pada, [T] untuk utas latar belakang dan [M] untuk utas Utama.
sumber
Pada XCode beta 6, Anda dapat menggunakan
reflect(self).summary
untuk mendapatkan nama kelas dan__FUNCTION__
untuk mendapatkan nama fungsi, tetapi hal-hal agak rusak, sekarang. Mudah-mudahan, mereka akan menemukan solusi yang lebih baik. Mungkin ada gunanya menggunakan #define hingga kami keluar dari beta.Kode ini:
NSLog("[%@ %@]", reflect(self).summary, __FUNCTION__)
memberikan hasil seperti ini:
2014-08-24 08:46:26.606 SwiftLessons[427:16981938] [C12SwiftLessons24HelloWorldViewController (has 2 children) goodbyeActiongoodbyeAction]
EDIT: Ini lebih banyak kode, tetapi membuat saya lebih dekat dengan apa yang saya butuhkan, yang menurut saya adalah apa yang Anda inginkan.
func intFromString(str: String) -> Int { var result = 0; for chr in str.unicodeScalars { if (chr.isDigit()) { let value = chr - "0"; result *= 10; result += value; } else { break; } } return result; } @IBAction func flowAction(AnyObject) { let cname = _stdlib_getTypeName(self) var parse = cname.substringFromIndex(1) // strip off the "C" var count = self.intFromString(parse) var countStr = String(format: "%d", count) // get the number at the beginning parse = parse.substringFromIndex(countStr.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) let appName = parse.substringToIndex(count) // pull the app name parse = parse.substringFromIndex(count); // now get the class name count = self.intFromString(parse) countStr = String(format: "%d", count) parse = parse.substringFromIndex(countStr.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) let className = parse.substringToIndex(count) NSLog("app: %@ class: %@ func: %@", appName, className, __FUNCTION__) }
Ini memberikan keluaran seperti ini:
2014-08-24 09:52:12.159 SwiftLessons[1397:17145716] app: SwiftLessons class: ViewController func: flowAction
sumber
Saya lebih suka mendefinisikan fungsi log global:
[Swift 3.1]
func ZYLog(_ object: Any?, filename: String = #file, line: Int = #line, funcname: String = #function) { #if DEBUG print("****\(Date()) \(filename)(\(line)) \(funcname):\r\(object ?? "nil")\n") #endif }
[Swift 3.0]
func ZYLog<T>(_ object: T?, filename: String = #file, line: Int = #line, funcname: String = #function) { #if DEBUG print("****\(Date()) \(filename)(\(line)) \(funcname):\r\(object)\n") #endif }
[Swift 2.0]
func ZYLog<T>(object: T, filename: String = __FILE__, line: Int = __LINE__, funcname: String = __FUNCTION__) { println("****\(filename.lastPathComponent)(\(line)) \(funcname):\r\(object)\n") }
outputnya seperti ini:
****ZYHttpSessionManager.swift(78) POST(_:parameters:success:failure:): [POST] user/login, { "auth_key" = xxx; "auth_type" = 0; pwd = xxx; user = "xxx"; } ****PointViewController.swift(162) loadData(): review/list [limit: 30, skip: 0] ****ZYHttpSessionManager.swift(66) GET(_:parameters:success:failure:): [GET] review/list, { "auth_key" = xxx; uuid = "xxx"; }
sumber
object
parameter dapat dinyatakan sebagaiAny
bukanT
.Ini adalah jawaban Swift 2 yang diperbarui.
func LogW(msg:String, function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__){ print("[WARNING]\(makeTag(function, file: file, line: line)) : \(msg)") } private func makeTag(function: String, file: String, line: Int) -> String{ let url = NSURL(fileURLWithPath: file) let className:String! = url.lastPathComponent == nil ? file: url.lastPathComponent! return "\(className) \(function)[\(line)]" }
Contoh penggunaan:
LogW("Socket connection error: \(error)")
sumber
__FUNCTION__ becomes #function, __FILE__ becomes #file, and __LINE__ becomes #line.
Atau sedikit modifikasi fungsi dengan:
func logFunctionName(file:String = __FILE__, fnc:String = __FUNCTION__, line:(Int)=__LINE__) { var className = file.lastPathComponent.componentsSeparatedByString(".") println("\(className[0]):\(fnc):\(line)")
}
/ * akan menghasilkan jejak eksekusi seperti: AppDelegate: application (_: didFinishLaunchingWithOptions :): 18 Product: init (type: name: year: price :): 34 FirstViewController: viewDidLoad (): 15 AppDelegate: applicationDidBecomeActive: 62 * /
sumber
Saya menggunakan, ini semua yang diperlukan dalam file swift, semua file lain akan mengambilnya (sebagai fungsi global). Ketika Anda ingin merilis aplikasi, cukup beri komentar.
import UIKit func logFunctionName(file:NSString = __FILE__, fnc:String = __FUNCTION__){ println("\(file.lastPathComponent):\(fnc)") }
sumber
Swift 3.0.0
public func LogFunction<T>(object: T, filename: String = #file, line: Int = #line, funcname: String = #function) { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MM/dd/yyyy HH:mm:ss:SSS" let process = ProcessInfo.processInfo() let threadId = "?" print("\(dateFormatter.string(from:Date())) \(process.processName) [\(process.processIdentifier):\(threadId)] \(filename)(\(line)) \(funcname)::: \(object)") }
sumber
Cepat 3.x +
Jika Anda tidak menginginkan seluruh nama file maka berikut adalah perbaikan cepat untuk itu.
func trace(fileName:String = #file, lineNumber:Int = #line, functionName:String = #function) -> Void { print("filename: \(fileName.components(separatedBy: "/").last!) function: \(functionName) line: #\(lineNumber)") } filename: ViewController.swift function: viewDidLoad() line: #42
sumber
Cara lain untuk mencatat panggilan fungsi:
NSLog("\(type(of:self)): %@", #function)
sumber