Swift NSLog是否有快捷的替代方案(“s”、“漂亮”函数)

Swift NSLog是否有快捷的替代方案(“s”、“漂亮”函数),swift,Swift,在目标C中,您可以使用以下方法记录正在调用的方法: NSLog(@"%s", __PRETTY_FUNCTION__) 通常,这是从日志宏中使用的 虽然Swift不支持宏的(我想),但我仍然希望使用一个通用的log语句,其中包含被调用函数的名称。在斯威夫特有可能吗 更新: 我现在使用这个全局函数进行日志记录,可以在这里找到: 您可以使用以下方式安装: pod 'Stuff/Print' 代码如下: public class Stuff { public enum logLevel:

在目标C中,您可以使用以下方法记录正在调用的方法:

NSLog(@"%s", __PRETTY_FUNCTION__)
通常,这是从日志宏中使用的

虽然Swift不支持宏的(我想),但我仍然希望使用一个通用的log语句,其中包含被调用函数的名称。在斯威夫特有可能吗

更新: 我现在使用这个全局函数进行日志记录,可以在这里找到: 您可以使用以下方式安装:

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 "Swift has 
#file
,
#function
,
#line
and
#column
. From Swift Programming Language:

#file
- String - The name of the file in which it appears.

#line
- Int - The line number on which it appears.

#column
- Int - The column number in which it begins.

#function
- String - The name of the declaration in which it appears.

As of XCode beta 6, you can use
reflect(self).summary
to get the class name and
__FUNCTION__
to get the function name, but things are a bit mangled, right now. Hopefully, they'll come up with a better solution. It might be worthwhile to use a #define until we're out of beta.

This code:

NSLog("[%@ %@]", reflect(self).summary, __FUNCTION__)
公共类的东西{
公共枚举日志级别:Int{
案例信息=1
案例调试=2
案例警告=3
案例错误=4
致命个案=5
案例无=6
public func description()->字符串{
切换自身{
案例信息:
返回“❓"
case.debug:
返回“✳️"
案例。警告:
返回“⚠️"
案例.错误:
return“Swift有
#文件
#函数
#行
#列
。来源:

#file
-字符串-显示该文件的文件名

#line
-Int-显示该行的行号

#column
-Int-开始的列号


#function
-String-它出现的声明的名称。

从XCode beta 6开始,您可以使用
反射(self).summary
来获取类名,而
来获取函数名,但是现在事情有点混乱。希望他们能想出一个更好的解决方案。在测试版结束之前,使用#define可能是值得的

此代码:

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__)
}
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
}
编辑:这是更多的代码,但让我更接近我所需要的,我认为这正是您想要的

2014-08-24 09:52:12.159 SwiftLessons[1397:17145716] app: SwiftLessons class: ViewController func: flowAction
它给出如下输出:

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__)
}
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.1]

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
}
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 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
}
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文件中所需的全部内容,所有其他文件都将使用它(作为全局函数)。 当您想要发布应用程序时,只需注释掉该行即可

func logFunctionName(file:String = __FILE__, fnc:String = __FUNCTION__, line:(Int)=__LINE__) {
    var className = file.lastPathComponent.componentsSeparatedByString(".")
    println("\(className[0]):\(fnc):\(line)")
或轻微的功能修改,包括: }

/*将生成执行跟踪,如: AppDelegate:application(uquo:didfishlaunchingwithoptions:):18 产品:初始(类型:名称:年份:价格:):34 FirstViewController:viewDidLoad():15 AppDelegate:ApplicationIDBecomeActive:62
*/Swift 4
以下是我的方法:

pretty_function()
将其设为全局函数并调用

NSLog("\(type(of:self)): %@", #function)

额外好处:您将看到后台线程在[T]上执行,主线程在[M]上执行。

记录函数调用的另一种方法:

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

以下是最新的Swift 2答案

LogW("Socket connection error: \(error)")
使用示例:

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

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

  • #file(字符串)显示该文件的文件名
  • #line(Int)它出现的行号
  • #column(Int)它开始的列号
  • #function(字符串)它出现的声明的名称
来自第894页的

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.0

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
public func LogFunction(object:T,filename:String=#file,line:Int=#line,funcname:String=#function){
让dateFormatter=dateFormatter()
dateFormatter.dateFormat=“MM/dd/yyyy HH:MM:ss:SSS”
让process=ProcessInfo.ProcessInfo()
让threadId=“?”
打印(“\(dateFormatter.string(from:Date())\(process.processName)[\(process.processIdentifier):\(threadId)]\(文件名)(\(行))\(funcname::\(对象)”)
}

Swift 3.x+

如果您不想要整个文件名,那么这里有一个快速修复方法


当然——这些都是从C中转发过来的。但这并没有回答关于
\uu PRETTY\u FUNCTION\uuu
的问题,这不是很容易从给定的选项中创建的。(是否有
\uu CLASS\uuuu
?如果有,那会有帮助。)在Swift 2.2中应该使用函数、文件和其他,如图所示:我使用
NSLog(“Running%@:%@”,NSStringFromClass(self.dynamicType),\uuuu FUNCTION\uuuuu)
我使用我认为你的日志风格应该是“漂亮函数”的定义。感谢分享。需要将文件声明从String更改为NSString。String.Awesome dude上没有lastPathComponent。Swift>2.1的微小更改:“println”已重命名为“print”。print(“file:(file.debugDescription)function:(function)line:(line)”)很酷,很好用。能够以某种方式将类/对象传递给它也很好(一个选项是使用显式自参数)。谢谢。您的方法有问题:-此函数不是线程安全的。如果您同时从不同的线程调用它,请准备好一些糟糕的惊喜-使用全局函数是不好的做法您实际上不需要在这里使用泛型函数,因为
对象
参数可以声明为
Any
,而不是
t
。这非常好。但是再次强调,..LogW不能与print()完全相同使用(参数用逗号分隔)…“LogW不能与print()完全相同使用(参数用逗号分隔)“我想添加此支持,但我发现我不需要它。”LogW(“套接字连接错误:(错误)其他信息:(其他信息)”“是的。我做了一些修改,发现唯一的解决方案是使用extra()保存语句,使其尽可能类似于print()。无论如何,使用您的答案创建了此语句,非常感谢!”)非常有用!从Swift 2.2开始,
\uuuuuu函数变成了#函数,uuu文件变成了#文件,uuu行变成了#行。
我们遇到了新值的问题。我们将等到Swift 3更新我们的代码库。这应该被标记为当前正确的答案。