Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect print to a File like redirecting NSLog to a file

Tags:

ios

swift

nslog

I have redirected NSLog to a file using the macros.

But I couldn't find a stable way in swift to do that.

As of now I am doing a workaround

I define the following method so whenever I call print in the file it comes here and I write that to a file.

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

But problems with this approach are

1.I will get Extra Argument in Call If I do like below

print("some comments",Obj1,Obj2)

so I have to use like this

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

2.I will get error like Cannot convert value of type '[AnyObject]' to expected argument type 'String!' If I try to print an object directly

print(obj)

so I have to call the description method of the object

print(obj.description)

3.I have to include the function definition that I have quoted above wherever I want this functionality But in the case of NSLog its globally defined in one place

so Now I am looking for a stable solution to redirect the contents of print in swift to a file

so I can use print as I do normally in swift

Update:

I tried overriding the print but I got Method does not override any method from its superclass

like image 536
Durai Amuthan.H Avatar asked Jan 06 '23 14:01

Durai Amuthan.H


1 Answers

First, overriding NSLog with a macro is really bad approach. Just use a different function name and use that. Overriding print is even more fragile. Just name it something else. When someone sees NSLog or print in the code, it shouldn't be a trick.

That said, it'll generally work within a given module, as long as you give it the right signature:

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

(EDIT: Fixed up the signature to be very explicit on exactly how print does it, rather than just showing the docs.)

You didn't use varargs syntax (...) in your function, which is why it doesn't accept multiple parameters. And if you want it to accept non-Strings (like obj) then you have to accept Any, not just String.

If you just make your own printlog function (or whatever you want to call it), then of course you can use whatever signature is convenient, but if you're going to overload print, you'll need to match its signature and functionality.

Here's the full implementation. This is a terrible way to do it. You should not override print. But this is how Swift allows it to be done (spread across three files just to demonstrate that it's working):

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
}

Again, this is a horrible idea. It is far better, flexible, and clearer to just create a new function. But Swift definitely can do it.

As a note, if your real goal is just to write stdout or stderr to a file, there's no need to override print or NSLog this way. Just reopen your stdout and/or stderr. For example:

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

That would redirect stderr. Use stdout to get stdout. This will work for anything that prints to stdout/err, no matter what module does it.

like image 180
Rob Napier Avatar answered Jan 27 '23 11:01

Rob Napier