Enhance Your SwiftUI Live Preview Workflow with PreviewLogger
Sergey Neskoromny
Android and iOS Expert | Software Engineer | LLM Applications Enthusiast.
Update on Apr 4 2023
I usually have no problem to switch between different platforms and programming languages. It typically takes me just a few days to get back into the flow of things when transitioning between Swift and Kotlin, Studio and XCode. However, this time was different. After working on an Android project for a month, I returned to Xcode and faced a challenge. The Live Preview wasn’t displaying the logs I needed to debug my project. Though inconvenient, I thought, it’s similar to not being able to see logs in Android Studio Compose Preview, so let’s stay determined to find a solution!
I spent a few hours trying to resolve the issue and eventually found a solution, which I decided to share in this article. However, a few days later, after restarting Xcode, I realized that the preview was actually printing the logs just fine. It turned out to be an Xcode glitch, which was a bit frustrating, but I learned an important lesson. When switching between different tools and platforms, it’s essential to shift your mindset and approach accordingly!
I chose to keep this article published as a testament to the time I spent on unnecessary work and as a friendly reminder to fellow engineers:?before you reinvent the wheel, take a moment to look around — maybe it’s already been invented!
“Debugging is like being the detective in a crime movie where you’re also the murderer.” — Filipe Fortes
Developing new components in large projects can be time-consuming, especially when you need to debug issues or monitor the state of your views. Thankfully, SwiftUI introduced live previews, allowing you to see your changes in real-time without needing to run the whole app in a simulator or on a device. But, what if you need to debug an issue or see logs during development? Unfortunately, Xcode’s SwiftUI preview doesn’t provide an out-of-the-box solution for displaying logs or debugging views. In this article, we’ll explore a custom solution called PreviewLogger that enables you to see logs directly in your SwiftUI previews and learn how it can save you time during development.
Benefits of PreviewLogger
Step-by-step guide to implementing PreviewLogger
Create a new Swift file called PreviewLogger.swift in your project.
Copy and paste the following code into the PreviewLogger.swift file:
领英推荐
import SwiftUI
struct ContentView: View {
@EnvironmentObject var previewLogger: PreviewLogger
var body: some View {
Button("Print Log") {
previewLogger.log("Button tapped in SwiftUI preview!")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(PreviewLogger.shared)
.previewWrapper()
}
}
struct PreviewWrapper: ViewModifier {
@EnvironmentObject var previewLogger: PreviewLogger
func body(content: Content) -> some View {
VStack {
content
List(previewLogger.logMessages.reversed(), id: \.self)
{ log in
Text(log)
}
}
}
}
extension View {
func previewWrapper() -> some View {
self.modifier(PreviewWrapper())
.environmentObject(PreviewLogger.shared)
}
}
class PreviewLogger: ObservableObject {
static let shared = PreviewLogger()
@Published private(set) var logMessages: [String] = []
func log(_ message: String) {
logMessages.append(message)
}
}
In your component's preview, use the .previewWrapper() modifier and provide the PreviewLogger.shared environment object:
struct YourComponent_Previews: PreviewProvider {
? ? static var previews: some View {
? ? ? ? YourComponent()
? ? ? ? ? ? .environmentObject(PreviewLogger.shared)
? ? ? ? ? ? .previewWrapper()
? ? }
}
Inject the PreviewLogger instance in your component using the @EnvironmentObject property wrapper:
struct YourComponent: View {
? ? @EnvironmentObject var previewLogger: PreviewLogger
? ? // ...
}
Use the?previewLogger.log()?method to log messages, which will appear directly below the preview:
Button("Print Log") {
? ? previewLogger.log("Button tapped in SwiftUI preview!")
}
Here is a PreviewLogger in the actions:
The PreviewLogger provides a convenient way to display logs directly in your SwiftUI previews, enabling a faster and more efficient development process. This custom solution lets you quickly test and debug individual components without running the entire app on a simulator or device. Give it a try in your projects and see how it can save you time and improve your workflow.
It’s worth noting that PreviewLogger may not be suitable for use within the rendering cycle of a view. According to Apple’s documentation on SwiftUI, modifying state or calling functions that participate in the rendering cycle from within a preview context can result in undefined behavior and should generally be avoided.
Lastly, I want to emphasize that any feedback on this article or PreviewLogger is greatly appreciated. Whether you have suggestions for improvement, alternative solutions, or just want to share your thoughts, please feel free to do so in the comments section below. I value your input and look forward to hearing from you!