Utilizing PreviewModifier to construct a previewing atmosphere – Donny Wals


Revealed on: July 10, 2024

Xcode 16 and iOS 18 include a characteristic that enables us to construct elaborate preview environments utilizing a brand new PreviewModifier protocol. This protocol permits us to outline objects that may create a single context or atmosphere that’s cached and used throughout your SwiftUI previews.

That is helpful as a result of it implies that you can, for instance, populate a database with a bunch of mock information that’s then utilized in your previews.

You too can use PreviewModifier to use particular styling to your previews, to wrap all of them in a particular wrapper, and extra.

Basically, they’re a software that permits you to configure your previews persistently throughout the board.

Adorning views utilizing PreviewModifier

The PreviewModifier protocol specifies two strategies which you could implement:

  • A static makeSharedContext methodology
  • An occasion methodology referred to as physique

The physique occasion strategies is handed the view that’s being previewed and a Context. This context can both be an object that you just created in makeSharedContext or Void for those who don’t implement makeSharedContext.

For this instance, let’s assume that you just went forward and didn’t implement makeSharedContext. In a state of affairs like that, we are able to use PreviewModifier to brighten a view for our previews. For instance, we may wrap it in one other view or apply some styling to it.

I’m fairly positive that you just’re extra inventive than me so I’m simply going to go forward and present you the way you’ll apply a orange background to your previewed view. Yeah, I do know… very inventive. The purpose is to indicate you the way to do that so to do one thing a lot smarter than what I’m describing right here.

struct OrangeBackground: PreviewModifier {
    func physique(content material: Content material, context: Void) -> some View {
        content material
            .padding()
            .background {
                RoundedRectangle(cornerRadius: 16)
                    .fill(.orange)
            }
    }
}

#Preview(traits: .modifier(OrangeBackground())) {
    Textual content("Hey, world!")
}

Let’s take a look at the PreviewModifier first, after which I’ll clarify how I utilized it to my preview.

The modifier is outlined as a struct and I solely carried out the physique perform.

This perform is padded Content material which is no matter view the #Preview macro is getting used on (on this case, Textual content), and it receives a context. On this case Void as a result of I didn’t make a context.

The content material argument might be styled, modified, and wrapped nonetheless you want. It’s a view so you are able to do issues like give it a background, remodel it, regulate its atmosphere, and far way more. Something you are able to do with a view inside a View physique you are able to do right here.

The primary distinction is that you just’re receiving a totally instantiated occasion of your view. Meaning you may’t inject new state or bindings into it or in any other case modify it. You possibly can solely apply view modifiers to it.

This brings us to our subsequent characteristic of PreviewModifier making a context to offer mocked information and extra.

Utilizing PreviewModifier to inject mock information

To inject mock information into your previews by PreviewModifier all you have to do is implement the makeSharedContext methodology from the PreviewModifier protocol. This methodology is static and is known as as soon as for all of your previews. Which means that the context that you just create on this methodology is reused for all your previews.

In apply that is good as a result of it means you get constant mock information on your previews with out the overhead of recreating this information continuously.

Right here’s what a pattern implementation for makeSharedContext seems like:

struct MockDataSource {
    // ...
}

struct OrangeBackground: PreviewModifier {
    static func makeSharedContext() async throws -> MockDataSource {
        return MockDataSource()
    }
}

On this case, I’m creating an occasion of some information supply in my makeSharedContext methodology. This MockDataSource would maintain all mocks and all information for my views which is nice.

Nevertheless, the one approach for us to essentially use that mock information in our view is by including our information supply (or the mocked information) to our previewed view’s atmosphere.

struct OrangeBackground: PreviewModifier {
    static func makeSharedContext() async throws -> MockDataSource {
        return MockDataSource()
    }

    func physique(content material: Content material, context: MockDataSource) -> some View {
        content material
            .atmosphere(.dataSource, context)
    }
}

Since we are able to’t make a brand new occasion of our content material, we are able to’t inject our mock information supply instantly into the view by its initializer. The one approach we are able to get the info supply to the view is by including it to the atmosphere.

This isn’t supreme for my part, however the design is sensible.

I’m additionally fairly positive that Apple designed this API with mocking SwiftData databases in thoughts and it could work nice for that.

On high of getting to make use of the atmosphere, the PreviewModifier solely works in tasks that focus on iOS 18 or later. Not an enormous downside however it could have been good if utilizing Xcode 16 was ok for us to have the ability to use this helpful new API.

Recent Articles

Related Stories

Leave A Reply

Please enter your comment!
Please enter your name here

Stay on op - Ge the daily news in your inbox