这个东西不是我写的,出自 StackOverFlow,但我觉得实在是写得太好了,于是截取了该部分分享出来,感谢原作者。
print function has changed completely since the late revision of Swift, now it looks much simpler and there are variant of method to print to standard console.
The method signature for print looks something like this,
public func print(items: Any...,
separator: String = default,
terminator: String = default,
inout toStream output: Target)
Notice that all other parameter except items takes default parameter, so you can either pass them while calling but they are not mandatory.
Basic version
print("Swift is awesome.")
Prints:
Swift is awesome.
Using separator
You can also use separator to concatenate multiple items and print them to console,
print("Swift", "is", "awesome", separator:" ")
Prints:
Swift is awesome
Using terminator
print("Swift", "is", "awesome", separator:" ", terminator:".")
Prints:
Swift is awesome.
When using terminator, it appends new prints on the same line.
Concatenating multiple prints
Assume two prints as follows:
print("This is wild", terminator: " ")
print("world")
This will print it like this,
This is wild world
So, using terminator, you should be careful that the contents are relevant to same line.
Printing Custom Object
Consider the following class Person, struct Address { let city: String }
class Person {
var name: String = "Jack"
var addresses:[Address] = [
Address(city: "Helsinki"),
Address(city: "Tampere")
]
}
You can have your custom string to be printed when you print an instance of class Person. For this, you can conform to CustomStringConvertible Protocol.
Overview This textual representation is used when values are written to an output stream, for example, by print.
extension Person: CustomStringConvertible {
var description: String {
return String(format: "", arguments:[unsafeAddressOf(self)])
}
}
let jack = Person()
print(jack)
This would then print something like this,
Consider that you want to use lldb to print something else, perhaps a more helpful information. You would then make your class conform to CustomDebugCovertible which is very similar to how CustomStringConvertible works,
Overview This textual representation is used when values are written to an output stream by debugPrint, and is typically more verbose than the text provided by a CustomStringConvertible's description property.
That means debugPrint uses this information to print to standard output.
How can you make use of it ?
Conforming Person class to this protocol,
extension Person: CustomDebugStringConvertible {
var debugDescription: String {
return String(format: "", arguments:[unsafeAddressOf(self)])
}
}
Now, you can use this information with lldb debugger and use po (print object) command,
> po person
Prints,
One cool thing about all these is that you can also provide your own custom stream using Streamable protocol, that requires you to implement method write(string: String). With that you could create your own network logger, file logger or some other form of printing mechanism.
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)!)
}
}
I could now create an instance of Streamer, and use it as a target stream to print, then all my logs go to the 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 one more interesting command related to printing that I want to mention,
Conforming to CustomReflectable gives a different perspective again how you look on 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 command po,
> po person
Result would be something like this,
▿
- name : "Jack"
▿ address1 : Address
- city : "Helsinki"
▿ address2 : Address
- city : "Tampere"