Xcode 11 - SwiftUI Preview Dark Mode

You should have something like this at the bottom of the file that's being previewed. This is what Xcode uses to generate the preview:

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

To change the preview to dark mode, you just need to specify a colorScheme:

static var previews: some View {
    ContentView().colorScheme(.dark)
}

Or, you can even chose to preview light and dark mode at the same time:

static var previews: some View {
    Group {
        ContentView().colorScheme(.light)
        ContentView().colorScheme(.dark)
    }
}

I recommend watching the Introducing SwiftUI session for more examples of SwiftUI and how powerful the previews can be.


TLDR:

Just add the .background(Color(UIColor.systemBackground)) and .environment(\.colorScheme, .dark) modifiers to the preview. For an explanation, examples, some modifications and a few tips to make it prettier and even simpler, please read the whole answer.

Explanation

I know this question is fairly old, but I've found a way that isn't too painful to implement and doesn't require any wrapping in a NavigationView. Furthermore, it also retains the correct behaviour of .previewLayout(.sizeThatFits).

Essentially, when you define a struct that conforms to PreviewProvider, you are only defining the content, but the background of the preview is managed for you by Xcode. Therefore, applying .environment(\.colorScheme, .dark) only changes the actual View to dark mode, but not the background. The reason NavigationView solves this issue is fairly simple - it adds a background to the view covering all of the preview's white background.

The fix itself is also fairly simple - all that you need to do is to add a background to your view in the preview. So for a simple view like this:

struct ExampleView: View {
    var body: some View {
        Text("Hello, World!")
    }
}

And a set of previews like this:

struct ExampleView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ExampleView()
            ExampleView()
                .environment(\.colorScheme, .dark)
        }.previewLayout(.sizeThatFits)
    }
}

You get an output that looks like this:

Light and dark mode rendering of ExampleView above

In order to make the second preview appear on a dark background, add it by calling .background(Color(UIColor.systemBackground)) on the View:

struct ExampleView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ExampleView()
            ExampleView()
                .background(Color(UIColor.systemBackground))
                .environment(\.colorScheme, .dark)
        }.previewLayout(.sizeThatFits)
    }
}

And you get two previews that look like this:

Light and dark mode rendering of ExampleView above with background fixes

Extra options

There are several modifications you could make. Firstly, depending on the layer the cell will be on you can replace UIColor.systemBackground with UIColor.secondarySystemBackground or UIColor.tertiarySystemBackground. Read more about dynamic system colours in the human interface guidelines or the UI Element Colors portion of the UIColor developer documentation.

Lastly, if you're going to be using this often and don't want to write out the whole call to UIColor every time, it might be a good idea to create an extension on Color and define them as static variables there:

extension Color {
    static let systemBackground = Color(UIColor.systemBackground)
    static let secondarySystemBackground = Color(UIColor.secondarySystemBackground)
    static let tertiarySystemBackground = Color(UIColor.tertiarySystemBackground)
}

Then you can replace your calls to Color(UIColor.systemBackground) with a much nicer Color.systemBackground.