Skip to content

Instantly share code, notes, and snippets.

@mflknr
Last active October 19, 2023 20:46
Show Gist options
  • Save mflknr/f25bb09e74085efb9b13b79715262130 to your computer and use it in GitHub Desktop.
Save mflknr/f25bb09e74085efb9b13b79715262130 to your computer and use it in GitHub Desktop.
Convenience extension for SwiftUI previews.
//
// PreviewExt.swift
//
//
// Created by Marius Felkner on 2021-11-15.
//
// The MIT License (MIT)
//
// Copyright (c) 2021 Marius Felkner (https://twitter.com/mflknr)
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// *****WARNING*****
// SINCE THE INTRODUCTION OF MACROS AND THE NEW PREVIEW CONTEXT
// THIS BECAME HEAVILY OUTDATED. USE WITH CAUTION OR JUST AS INSPIRATION
// *****WARNING*****
import SwiftUI
extension View {
func withColorSchemes() -> some View {
_PreviewColorScheme(content: self)
}
@available(iOS 15.0, *)
func withInterfaceOrientations() -> some View {
_PreviewInterfaceOrientations(content: self)
}
func asComponent() -> some View {
_PreviewComponent(content: self)
}
func onDevices(devices: [PreviewDevices] = [.iPhone6s, .iPhone13ProMax]) -> some View {
_PreviewDevices(content: self, devices: devices)
}
@available(iOS 15.0, *)
func withDynamicTypeSizes() -> some View {
_PreviewSizeCategory(content: self)
}
}
// MARK: - Prievew Wrapper
struct _PreviewColorScheme<Content: View>: View {
// MARK: - Properties
var content: Content
// MARK: - Body
var body: some View {
Group {
self.content
.preferredColorScheme(.light)
self.content
.preferredColorScheme(.dark)
}
}
}
@available(iOS 15.0, *)
struct _PreviewInterfaceOrientations<Content: View>: View {
// MARK: - Properties
var content: Content
// MARK: - Body
var body: some View {
Group {
self.content
.previewInterfaceOrientation(.portrait)
self.content
.previewInterfaceOrientation(.landscapeRight)
}
}
}
struct _PreviewComponent<Content: View>: View {
// MARK: - Properties
var content: Content
// MARK: - Body
var body: some View {
Group {
self.content
.previewLayout(.sizeThatFits)
}
}
}
struct _PreviewDevices<Content: View>: View {
// MARK: - Properties
var content: Content
var devices: [PreviewDevices]
// MARK: - Body
var body: some View {
Group {
ForEach(devices, id: \.self) { device in
self.content
.previewDevice(PreviewDevice.init(rawValue: device.rawValue))
.previewDisplayName(device.rawValue)
}
}
}
}
@available(iOS 15.0, *)
struct _PreviewSizeCategory<Content: View>: View {
// MARK: - Properties
var content: Content
private let dynamicTypeSizes: [DynamicTypeSize] = [
DynamicTypeSize.allCases.first ?? DynamicTypeSize.xSmall,
DynamicTypeSize.allCases.last ?? DynamicTypeSize.accessibility5
]
// MARK: - Body
var body: some View {
Group {
self.content
.previewDisplayName("Default")
ForEach(dynamicTypeSizes, id: \.self) {
self.content
.environment(\.dynamicTypeSize, $0)
.previewDisplayName("\($0)")
}
}
}
}
// MARK: - Preview Devices | iPhone and iPad devices from `xcrun simctl list devicetypes` on 2021-11-15
enum PreviewDevices: String, Hashable {
case iPhone4s = "iPhone 4s"
case iPhone5 = "iPhone 5"
case iPhone5s = "iPhone 5s"
case iPhone6Plus = "iPhone 6 Plus"
case iPhone6 = "iPhone 6"
case iPhone6s = "iPhone 6s"
case iPhone6sPlus = "iPhone 6s Plus"
case iPhoneSE_1stGen = "iPhone SE (1st Gen)"
case iPhone7 = "iPhone 7"
case iPhone7Plus = "iPhone 7 Plus"
case iPhone8 = "iPhone 8"
case iPhone8Plus = "iPhone 8 Plus"
case iPhoneX = "iPhone X"
case iPhoneXs = "iPhone Xs"
case iPhoneXsMax = "iPhone Xs Max"
case iPhoneXʀ = "iPhone Xʀ"
case iPhone11 = "iPhone 11"
case iPhone11Pro = "iPhone 11 Pro"
case iPhone11ProMax = "iPhone 11 Pro Max"
case iPhoneS_2ndGen = "iPhone SE (2nd Gen)"
case iPhone12mini = "iPhone 12 mini"
case iPhone12 = "iPhone 12"
case iPhone12Pro = "iPhone 12 Pro"
case iPhone12ProMax = "iPhone 12 Pro Max"
case iPhone13Pro = "iPhone 13 Pro"
case iPhone13ProMax = "iPhone 13 Pro Max"
case iPhone13mini = "iPhone 13 mini"
case iPhone13 = "iPhone 13"
case iPad2 = "iPad 2"
case iPadRetina = "iPad Retina"
case iPadAir = "iPad Air"
case iPadmini2 = "iPad mini 2"
case iPadmini3 = "iPad mini 3"
case iPadmini4 = "iPad mini 4"
case iPadAir2 = "iPad Air 2"
case iPadPro_9_7 = "iPad Pro (9.7-inch)"
case iPadPro_12_9_1stGen = "iPad Pro (12.9-inch) (1st generation)"
case iPad_5thGen = "iPad (5th generation)"
case iPadPro_12_9_2ndGen = "iPad Pro (12.9-inch) (2nd generation)"
case iPadPro_10_5 = "iPad Pro (10.5-inch)"
case iPad_6thGen = "iPad (6th generation)"
case iPad_7thGen = "iPad (7th generation)"
case iPadPro_11_1stGen = "iPad Pro (11-inch) (1st generation)"
case iPadPro_12_9_3rdGen = "iPad Pro (12.9-inch) (3rd generation)"
case iPadPro_11_2ndGen = "iPad Pro (11-inch) (2nd generation)"
case iPadPro_12_9_4thGen = "iPad Pro (12.9-inch) (4th generation)"
case iPadmini_5thGen = "iPad mini (5th generation)"
case iPadAir_3rdGen = "iPad Air (3rd generation)"
case iPad_8thGen = "iPad (8th generation)"
case iPad_9thGen = "iPad (9th generation)"
case iPadAir_4thGen = "iPad Air (4th generation)"
case iPadPro_11_3rdGen = "iPad Pro (11-inch) (3rd generation)"
case iPadPro_12_9_5thGen = "iPad Pro (12.9-inch) (5th generation)"
case iPadmini_6thGen = "iPad mini (6th generation)"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment