是否有NSLog的替代(@“%s”,__PRETTY_FUNCTION__)

在Objective C中,您可以使用以下方法logging正在调用的方法:

NSLog(@"%s", __PRETTY_FUNCTION__) 

通常这是从一个日志macros使用。

虽然Swift不支持macros的(我认为)我仍然想使用一个通用的日志语句,包括被调用的函数的名称。 在Swift中可能吗?

更新:我现在使用这个全局函数进行日志logging,可以在这里find: https : //github.com/evermeer/Stuff#print你可以使用安装:

 pod 'Stuff/Print' 

这里是代码:

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

你可以这样使用:

 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) 

这将导致:

 ✳️ .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 

Swift有#file#file#column#column 。 来自Swift编程语言 :

#file – string – 它出现的文件的名称。

#line – Int – 显示的行号。

#column – Int – 它开始的列号。

#function – String – 显示的声明的名称。

从Swift 2.2开始,我们应该使用:

  • #file (string)它出现的文件的名称。
  • #line (Int)它出现的行号。
  • #column (Int)它开始的列号。
  • #function (String)它出现的声明的名字。

Swift编程语言(Swift 3.1) ,第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 

这是我的方法:

 func pretty_function(file:String = __FILE__, function:String = __FUNCTION__, line:Int = __LINE__) { print("file:\(file.lastPathComponent) function:\(function) line:\(line)") } 

使这个全局函数,只是打电话

 pretty_function() 

从XCode beta 6开始,您可以使用reflect(self).summary获取类名,使用__FUNCTION__获取函数名,但是现在情况有些变了。 希望他们能拿出更好的解决scheme。 使用#define可能是值得的,直到我们没有testing。

此代码:

 NSLog("[%@ %@]", reflect(self).summary, __FUNCTION__) 

给出这样的结果:

 2014-08-24 08:46:26.606 SwiftLessons[427:16981938] [C12SwiftLessons24HelloWorldViewController (has 2 children) goodbyeActiongoodbyeAction] 

编辑:这是更多的代码,但让我更接近我所需要的,我认为是你想要的。

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

它给出这样的输出:

 2014-08-24 09:52:12.159 SwiftLessons[1397:17145716] app: SwiftLessons class: ViewController func: flowAction 

我更喜欢定义一个全局日志function:

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

输出是这样的:

 ****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"; } 

这是一个更新的Swift 2的答案。

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

使用示例:

 LogW("Socket connection error: \(error)") 

或轻微的function修改:

 func logFunctionName(file:String = __FILE__, fnc:String = __FUNCTION__, line:(Int)=__LINE__) { var className = file.lastPathComponent.componentsSeparatedByString(".") println("\(className[0]):\(fnc):\(line)") 

}

/ *会产生一个执行跟踪:AppDelegate:application(_:didFinishLaunchingWithOptions :):18产品:init(types:name:year:价格:):34 FirstViewController:viewDidLoad():15 AppDelegate:applicationDidBecomeActive:

logging函数调用的另一种方法:

 NSLog("\(self.dynamicType): %@", __FUNCTION__) 

我使用,这是一个迅速文件所需的所有,所有其他文件将把它(作为一个全局函数)。 当你想发布的应用程序只是注释掉行。

 import UIKit func logFunctionName(file:NSString = __FILE__, fnc:String = __FUNCTION__){ println("\(file.lastPathComponent):\(fnc)") } 

Swift 3.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)") } 

Swift 3.x +

如果你不想要整个文件名,那么这里是一个快速的解决scheme。

 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