将打印重定向到文件,例如将 NSLog 重定向到文件

Redirect print to a File like redirecting NSLog to a file

我已使用宏将 NSLog 重定向到 文件

但是我在 swift 中找不到一个稳定的方法来做到这一点。

目前我正在做一个解决方法

我定义了以下方法,所以每当我在文件中调用 print 时,它都会出现在这里,然后我将其写入文件。

func print(log:String!) {
        if let logg = log {
            DeveloperConsoleManager.sharedInstance.writeOnConsoleLog(logg)
        }
    }

但是这种方法的问题是

1.I 将获得 调用中的额外参数 如果我喜欢下面

print("some comments",Obj1,Obj2)

所以我必须这样使用

print("some comments \(Obj1) \(Obj2)")

2.I 会出现类似 Cannot convert value of type '[AnyObject]' to expected argument type 'String!' 如果我尝试打印一个对象直接

print(obj)

所以我要调用对象的描述方法

print(obj.description)

3.我必须在任何需要此功能的地方包含我在上面引用的函数定义但是在 NSLog 的情况下,它在一个地方全局定义

所以现在我正在寻找一个稳定的解决方案来将swift中print的内容重定向到一个文件

所以我可以像在 swift

中一样使用 print

更新:

我尝试覆盖打印但我得到 方法没有覆盖其超类中的任何方法

首先,用宏覆盖 NSLog 是非常糟糕的方法。只需使用不同的函数名称并使用它。覆盖 print 更加脆弱。只是给它起个别的名字。当有人在代码中看到 NSLogprint 时,应该不是骗人的

也就是说,它通常会在给定的模块中工作,只要您给它正确的签名:

public func print(items: Any..., separator: String = "", terminator: String = "\n")

(编辑:修复了签名以非常明确地说明 print 是如何做到的,而不仅仅是显示文档。)

您没有在函数中使用可变参数语法 (...),这就是它不接受多个参数的原因。如果你想让它接受非字符串(比如 obj),那么你必须接受 Any,而不仅仅是 String.

如果你只是创建自己的 printlog 函数(或任何你想调用它的东西),那么当然你可以使用任何方便的签名,但如果你要重载 print,您需要匹配其签名和功能。

这是完整的实现。这是一种糟糕的方法。你不应该覆盖 print。但这就是 Swift 允许它完成的方式(分布在三个文件中只是为了证明它正在工作):

main.swift:

func print(items: Any..., separator: String = "", terminator: String = "\n") {
    Swift.print("My print is printing \(items)", separator: separator, terminator: terminator)
}

print("In main!")
file1print()
file2print()

file1.swift:

func file1print() {
    print("file1!") // Calls our print
}

file2.swift:

func file2print() {
    print("file2!") // Calls our print
}

同样,这是一个糟糕的想法。只创建一个新函数会更好、更灵活、更清晰。但是Swift绝对可以做到。

请注意,如果您的真正目标只是将 stdout 或 stderr 写入文件,则无需以这种方式覆盖 print 或 NSLog。只需重新打开您的标准输出 and/or 标准错误。例如:

let path: NSString = ...;
freopen(path.UTF8String, "a+", stderr)

那会重定向 stderr。使用 stdout 获取标准输出。这将适用于打印到 stdout/err 的任何内容,无论哪个模块执行它。

如果我敢于切线...

重定向 NSLog 最安全的方法是重定向其 输出 而不是试图抓住为其提供输入的人。

How to redirect STDOUT to a NSTextView? 的答案是一个合适的起点 — NSPipeNSFileHandledup2 也都可以在 iOS 上找到。