How to print() to Xcode console in SwiftUI?
Solution 1:
At least in Xcode 12/Swift 5.3, you can easily add a print statement anywhere in a function builder by simply storing its return value in a wildcard, effectively ignoring it:
let _ = print("hi!")
No setup or other verbosity needed!
Solution 2:
Here's a helper Print( ... )
View that acts like a print( ... )
function but within a View
Put this in any of your view files
extension View {
func Print(_ vars: Any...) -> some View {
for v in vars { print(v) }
return EmptyView()
}
}
and use inside of body
like so
Print("Here I am", varOne, varTwo ...)
or inside a ForEach {}
like so
self.Print("Inside ForEach", varOne, varTwo ...)
Note: you might need to put Print()
into a Group {}
when combining with existing views
Solution 3:
Try right-clicking on the live preview play button and selecting 'Debug Preview from the popup
Solution 4:
You can print in the body structure but to do so you have to explcitly return the view you want to render. Normally in SwiftUI, the body property implicitly returns the view. For example, this will throw an error when you try to print:
struct SomeView: View {
@State var isOpen = false
var body: some View {
print(isOpen) // error thrown here
VStack {
// other view code
|
}
}
But if we explicitly return the view we want then it will work e.g.
struct SomeView: View {
@State var isOpen = false
var body: some View {
print(isOpen) // this ok because we explicitly returned the view below
// Notice the added 'return' below
return VStack {
// other view code
}
}
}
The above will work well if you're looking to view how state or environment objects are changing before returning your view, but if you want to print something deeper down within the view you are trying to return, then I would go with @Rok Krulec answer.
Solution 5:
It is possible to use print() remembering that all SwiftUI View content are (a) implicit closures and (b) it is highly recommended to decompose views as much as possible to have simple structure, so it might look like the following...
struct Model: Identifiable {
let value: String
var id: String {
value
}
init (_ value: String) {
self.value = value
}
}
struct TestView: View {
@State var showFavoritesOnly = false
@State var listData: [Model] = [Model("one"), Model("two"), Model("three")]
var body: some View {
NavigationView {
List {
Toggle(isOn: $showFavoritesOnly) {
Text("Favorite only")
}
ForEach(listData) { data in
self.rowView(data: data)
}
}
}
}
private func rowView(data: Model) -> some View {
#if DEBUG
print(">> \(data.value)")
#endif
return NavigationLink(destination: Text("Details")) {
Text("Go next from \(data.value)")
}
}
}
... and right clicking in Preview to select run as Debug Preview we get:
2019-10-31 14:28:03.467635+0200 Test[65344:11155167] [Agent] Received connection, creating agent
2019-10-31 14:28:04.472314+0200 Test[65344:11155168] [Agent] Received display message
>> one
>> two
>> three