Swift 中自定义Log

作者: LazyLoad | 来源:发表于2018-04-16 14:41 被阅读28次

    前言

    在使用Objective-C开发过程中,我们经常要自定义Log,原因很简单:

    • 在Debug模式里的log打印,可以帮助我们更好的调试代码,在Release模式里面,用户没有必要看到Log的打印;
    • OC中NSLog 会占用很大的内存资源。
      通常在OC中,自定义Log写在pch文件中,通过宏定义。
      在Swift中,没有宏这个概念了,我们该如何解决呢?

    几个问题

    允许我卖个关子,先不谈,debug还是release该怎么自定义Log。先谈一下,我们打印的时候遇到的问题。根据问题来一步步解决
    1、Swift中print函数,不会再占用很大的资源,但是在release模式下,确实没有必要打印Log,其实我想说,Swift 中print确实做了很多优化,但是也存在一些问题,看如下代码

    print("123")
    
    123
    123
    

    我在分别在两个函数里,打印了"123"字符串,可是我并不知道,"123"到底是在哪打印的,在哪个文件或者在哪个函数中,一脸懵逼
    所以我想知道我在哪个文件中打印的这句话,Swift可以这样搞:

            let file = #file
            print(file)
    结果:/Users/bh/Desktop/test/test/ViewController.swift
    

    这样就可以把具体哪个文件打印出来了,就是那个绝对路径。
    绝对路径很烦,因为前面那些xxx我根本不需要,所以我优化了一下,如下:

            let file = #file
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName)-123")
    
    结果:
    AppDelegate.swift-123
    ViewController.swift-123
    

    很明显,我知道了在哪个文件中打印了123。
    2、我虽然知道了在哪个文件中打印了123,但是如果放在同一个文件中的两个方法里面呢?

    override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            
            let file = #file
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName)-123")
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            
            let file = #file
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName)-123")
        }
    
    ViewController.swift-123
    ViewController.swift-123
    

    还是区别不出来,接下来我进一步优化,有两种方式,一种是

      override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            
            let file = #file
            let fileName = (file as NSString).lastPathComponent
    
            
            let funcName = #function
            print("\(fileName):[\(funcName)]-123")
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            
            let file = #file
            let fileName = (file as NSString).lastPathComponent
            
            let funcName = #function
            print("\(fileName):[\(funcName)]-123")
        }
        }
    
    打印结果:
    ViewController.swift:[viewDidLoad()]-123
    ViewController.swift:[viewWillAppear]-123
    

    还有另一种(个人偏爱这一种):

    override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            
            let file = #file
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName):(\(#line))-123")
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            
            let file = #file
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName):(\(#line))-123")
        }
    
    打印结果:
    
    ViewController.swift:(19)-123
    ViewController.swift:(27)-123
    

    这种方式,是告诉咱们,在多少行打印,简洁。

    3、接下来的问题是,我们不能每个方法里面都写这些代码,显得不专业,需要抽出一个方法来

    func BHLog(file: String, line: Int) {
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName):(\(#line))-123")
        }
    
    然后调用时候,BHLog(file: #file, line: #line) 这个样子,更烦了
    

    我们接下来,利用Swift中的 参数默认值解决:

    func BHLog(file: String = #file, line: Int = #line) {
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName):(\(line))-123")
        }
    
    BHLog()
    

    4、好像只剩下一下问题了,就是我们要打印的内容,我们不只是要打印String类型,可能是Int、Double或者是对象类型,所以我们需要再加个参数。

    func BHLog<T>(_ message: T, file: String = #file, line: Int = #line) {
            let fileName = (file as NSString).lastPathComponent
            print("\(fileName):(\(line))-\(message)")
        }
    

    泛型<T>,它代表着我们可以用T来代替实际类型,函数名后跟的那个 <T> 是函数定义的一个占位类型名,并不会查找T的具体类型。
    这样就解决了。
    5、剩下最后一个问题,我们有很多的类,不能够在每个类里都调用,这个函数,所以,我们利用Swift的全局函数,在任意一个类里面写个全局函数,就在所有的类中,可以调用了,我是写了个Global.swift 文件,你也可以卸载Appdelegate.swift中。

    最后小尾巴

    说了这么多,如何在Swift中,debug打印,而release中不打印呢,请继续看:


    image.png
    func BHLog<T>(_ message: T, file: String = #file, line: Int = #line) {
        
        #if DEBUG
        let fileName = (file as NSString).lastPathComponent
        print("\(fileName):(\(line))-\(message)")
        #endif
    }
    

    这样release就不会打印了,而在debug模式中会打印
    结束,美滋滋!

    相关文章

      网友评论

        本文标题:Swift 中自定义Log

        本文链接:https://www.haomeiwen.com/subject/jpxekftx.html