The print function has completely changed since the late revision of Swift, now it looks much simpler and there is a variant of the method for printing on a standard console.
The signature of the print method looks something like this:
public func print<Target : OutputStreamType>(items: Any..., separator: String = default, terminator: String = default, inout toStream output: Target)
Please note that all other parameters except the elements accept the default parameter, so you can pass them during the call, but they are optional.
Basic version
print("Swift is awesome.")
Print
Swift is awesome.
Using a delimiter
You can also use a separator to combine multiple items and print them to the console,
print("Swift", "is", "awesome", separator:" ")
Fingerprints:
Swift is wonderful
Use terminator
print("Swift", "is", "awesome", separator:" ", terminator:".")
Print
Swift is awesome.
When using the terminator, it adds new fingerprints on a single line.
Concatenation of multiple prints
Suppose two are printed as follows:
print("This is wild", terminator: " ") print("world")
It will be printed like this
This is wild world
So, using a terminator, you have to be careful that the content is relevant for the same line.
Printing a custom object
Consider the following Person class, struct Address {let city: String}
class Person { var name: String = "Jack" var addresses:[Address] = [ Address(city: "Helsinki"), Address(city: "Tampere") ] }
You can print your custom string when printing an instance of the Person class. To do this, you can conform to the CustomStringConvertible protocol.
Overview This text view is used when values ββare written to the output stream, for example, by printing. A.
extension Person: CustomStringConvertible { var description: String { return String(format: "<name: \(name) %p>", arguments:[unsafeAddressOf(self)]) } } let jack = Person() print(jack)
Then something like this will be printed,
<name: Jack 0x7fba7061be00>
Consider that you want to use lldb to print something else, possibly more useful information. Then you should make your class compatible with CustomDebugCovertible , which is very similar to the CustomStringConvertible method.
Overview This textual representation is used when values ββare written to the output stream using debugPrint and are usually more verbose than the text provided by the CustomStringConvertible property.
This means that debugPrint uses this information to print to standard output.
How can you use this?
Matching the Person class with this protocol,
extension Person: CustomDebugStringConvertible { var debugDescription: String { return String(format: "<name: \(name), addresses: \(addresses.map{$0.city}.reduce("", combine:{ $1 + " " + $0 })) %p>", arguments:[unsafeAddressOf(self)]) } }
Now you can use this information with lldb debugger and use the po (print object) command,
> po person
Print
<name: Jack, addresses: Tampere Helsinki 0x7fd0ad80f280>
One of the most interesting things is that you can also provide your own stream using the Streamable protocol, for which you need to implement the write (string: String) method. With this, you can create your own network recorder, file recorder or other printing mechanism. A.
Here is a simple version of my simple file logger that works with print or debugPrint,
struct MyStreamer: OutputStreamType { lazy var fileHandle: NSFileHandle? = { let fileHandle = NSFileHandle(forWritingAtPath: self.logPath) return fileHandle }() lazy var logPath: String = { let path : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first! let filePath = (path as NSString).stringByAppendingPathComponent("log.txt") if !NSFileManager.defaultManager().fileExistsAtPath(filePath) { NSFileManager.defaultManager().createFileAtPath(filePath, contents: nil, attributes: nil) } print(filePath) return filePath }() mutating func write(string: String) { print(fileHandle) fileHandle?.seekToEndOfFile() fileHandle?.writeData(string.dataUsingEncoding(NSUTF8StringEncoding)!) } }
Now I can create an instance of Streamer and use it as the target stream for printing, then all my logs go to a file,
var myStream = MyStreamer() print("First of all", toStream: &myStream ) print("Then after", toStream: &myStream) print("And, finally", toStream: &myStream)
Now my file contains the following logs,
First of all Then after And finally
Now there is another interesting printing team that I want to mention
Matching CustomReflectable gives a different perspective on how you look at the object and log debugger,
extension Person: CustomReflectable { func customMirror() -> Mirror { print("Mirror is called now") return Mirror(self, children: ["name": name, "address1": addresses[0], "address2": addresses[1]]) } }
Now, in lldb debugger, if you use the po command,
> po person
The result will be something like this
βΏ <name: Jack, addresses: Tampere Helsinki 0x7feb82f26e80> - name : "Jack" βΏ address1 : Address - city : "Helsinki" βΏ address2 : Address - city : "Tampere"