Есть ли быстрая альтернатива для NSLog (@"%s", довольно функция)
в 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 "
11 ответов:
Свифт
#file
,#function
,#line
и#column
. От Язык Программирования Swift:
#file
- String-имя файла, в котором он появляется.
#line
- Int-номер строки, на которой он появляется.
#column
- Int-номер столбца, в котором он начинается.
#function
- String-имя объявления, в котором оно появляется.
начиная с Swift 2.2 мы должны использовать:
- #file (строка) имя файла, в котором он появляется.
- # line (Int) номер строки, на которой он появляется.
- столбец# (Int) номер столбца, в котором он начинается.
- # function (строка) имя объявления, в котором оно появляется.
С Язык Программирования 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__
чтобы получить имя функции, но сейчас все немного искажено. Надеюсь, они найдут лучшее решение. Возможно, стоит использовать #define, пока мы не выйдем из бета-версии.этот код:
NSLog("[%@ %@]", reflect(self).summary, __FUNCTION__)
дает такие результаты:
2014-08-24 08:46:26.606 SwiftLessons[427:16981938] [C12SwiftLessons24HelloWorldViewController (has 2 children) goodbyeActiongoodbyeAction]
EDIT: это больше кода, но приблизил меня к тому, что мне нужно, что я думаю, что вы желаемый.
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 Продукт: init(тип: название: год:Цена:): 34 FirstViewController: viewDidLoad (): 15 AppDelegate:applicationDidBecomeActive: 62 * /
Я использую, это все, что требуется в swift-файле, все остальные файлы будут забирать его (как глобальную функцию). Когда вы хотите выпустить приложение, просто закомментируйте строку.
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+
Если вы не хотите, чтобы весь имя файла, то вот быстрое решение для этого.
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