[swift] NSLog (@“% s”, __PRETTY_FUNCTION__)에 대한 Swift 대안이 있습니까?

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



답변

스위프트가 #file, #function, #line#column. 에서 스위프트 프로그래밍 언어 :

#file -문자열-파일이 나타나는 파일의 이름입니다.

#line -Int-표시되는 줄 번호입니다.

#column -Int-시작하는 열 번호입니다.

#function -문자열-표시되는 선언의 이름입니다.


답변

Swift 2.2부터 다음을 사용해야합니다.

  • #file (문자열) 표시되는 파일의 이름입니다.
  • #line (Int) 표시되는 줄 번호입니다.
  • #column (Int) 시작되는 열 번호입니다.
  • #function (String) 표시되는 선언의 이름입니다.

에서 스위프트 프로그래밍 언어 (스위프트 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


답변

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]에서 실행되는 것을 볼 수 있습니다.


답변

XCode 베타 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


답변

전역 로그 함수를 정의하는 것을 선호합니다.

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


답변

또는 약간의 기능 수정 :

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 Product : init (type : name : year : price 🙂 : 34 FirstViewController : viewDidLoad () : 15 AppDelegate : applicationDidBecomeActive : 62 * /