在Objective C中,您可以使用以下命令记录正在调用的方法:
NSLog(@"%s", __PRETTY_FUNCTION__)
通常这是从记录宏中使用的。
虽然Swift不支持宏(我认为),但我仍然想使用包含被调用函数名称的通用日志语句。这在Swift中可能吗?
更新 我现在使用此全局函数进行日志记录,可在此处找到: 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
答案 0 :(得分:86)
Swift有#file
,#function
,#line
和#column
。来自Swift Programming Language:
#file
- String - 出现的文件的名称。
#line
- Int - 出现的行号。
#column
- Int - 开始的列号。
#function
- String - 出现的声明的名称。
答案 1 :(得分:65)
从Swift 2.2开始,我们应该使用:
第894页的 The Swift Programming Language (Swift 3.1) 。
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
答案 2 :(得分:17)
Swift 4
这是我的方法:
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]")
}
}
将此设为全局功能,然后调用
pretty_function()
奖励:您将看到线程被执行,[T]用于后台线程,[M]用于主线程。
答案 3 :(得分:9)
从XCode beta 6开始,你可以使用reflect(self).summary
来获取类名,使用__FUNCTION__
来获取函数名,但是现在有些事情已经被破坏了。希望他们能够提出更好的解决方案。在我们退出测试版之前使用#define可能是值得的。
此代码:
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
答案 4 :(得分:8)
我更喜欢定义全局日志功能:
[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";
}
答案 5 :(得分:5)
这是一个更新的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)")
答案 6 :(得分:0)
我使用,这是swift文件中所需的全部内容,所有其他文件都会将其拾取(作为全局函数)。 当您想要发布应用程序时,只需注释掉该行。
import UIKit
func logFunctionName(file:NSString = __FILE__, fnc:String = __FUNCTION__){
println("\(file.lastPathComponent):\(fnc)")
}
答案 7 :(得分:0)
func logFunctionName(file:String = __FILE__, fnc:String = __FUNCTION__, line:(Int)=__LINE__) {
var className = file.lastPathComponent.componentsSeparatedByString(".")
println("\(className[0]):\(fnc):\(line)")
}
/ *将生成执行跟踪,如: AppDelegate中:应用程序(_中:didFinishLaunchingWithOptions :):18 产品:初始化(类型:名称:年:价格:):34 FirstViewController:viewDidLoad中():15 AppDelegate中:applicationDidBecomeActive:62 * /
答案 8 :(得分:0)
记录函数调用的另一种方法:
NSLog("\(type(of:self)): %@", #function)
答案 9 :(得分:0)
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)")
}
答案 10 :(得分:0)
Swift 3.x +
如果您不想要整个文件名,那么可以快速解决此问题。
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