Swift ui 185

How to observe optional ObservableObject in SwiftUI

Issue #988

When working with Core Data, there are times we have optional NSManagedObject to pass around. These objects conform to ObservableObject, and in SwiftUI we can’t @ObservedObject on optional ObservableObject

One way we can workaround …

How to clear background for TextField inside list in macOS

Issue #986

When using TextField in SwiftUI List on Mac, it has unwanted background color when focused. We can turn it off using introspection or a custom TextField wrapper

TextField("Search", text: $searchText)
    .introspect(.textField, on: …

How to conditionally render widgets in iOS

Issue #984

The WidgetBundle lets us expose multiple widgets from a single widget extension

It uses WidgetBundleBuilder to constructs a widget bundle’s body.

In iOS 18, if we include ControlWidget then we need to check iOSApplicationExtension iOS 18. …

How to open app with Control Widget on iOS 18

Issue #983

In iOS 18, we can make Control Widget in Widget extension

import WidgetKit
import SwiftUI

@available(iOS 18.0, *)
struct BookControlWidget: ControlWidget {
    var body: some ControlWidgetConfiguration {
        StaticControlConfiguration …

How to make NSCollectionView with diffable data source and SwiftUI

Issue #980

NSCollectionView, available since macOS 10.5+, is a good choice to present a list of content. Let’s make a SwiftUI wrapper for NSCollectionView with diffable data source and compositional layout

Use NSViewControllerRepresentable …

How to handle tap gesture in SwiftUI Charts

Issue #978

From iOS 17, SwiftUI Charts has chartGesture, together with SpatialTapGesture we can check tap location and convert that to Charts value

Chart {}
    .chartGesture { chart in
        SpatialTapGesture()
            .onEnded { value in …

How to make attributed TextView for macOS and iOS with SwiftUI

Issue #956

macOS

import Foundation
import SwiftUI
import AppKit

struct AttributedTextView: NSViewRepresentable {
    @Binding var attributedText: NSAttributedString
    var isEditable: Bool = true
    
    final class Coordinator: NSObject { …

How to show anchor bottom view in SwiftUI

Issue #954

From iOS 15, there’s a handy safeAreaInset that allows us to place additional content extending the safe area.

Shows the specified content beside the modified view.

safeAreaInset allows us to customize which edge and alignment we …

How to drag multiple files in SwiftUI on Mac

Issue #951

Create a custom NSView that handles mouseDragged to beginDraggingSession

struct DraggingSourceViewWrapper: NSViewRepresentable {
    let fileUrls: [URL]
    let onEnd: () -> Void
    
    func makeNSView(context: Context) -> …

How to store Codable in AppStorage

Issue #949

AppStorage and SceneStorage accepts RawRepresentable where value is Int or String.

Creates a property that can read and write to a string user default, transforming that to RawRepresentable data type.

init(wrappedValue:_:store:)

init( …

How to update widget for iOS 17

Issue #948

iOS 17 has a new Stand by mode so SwiftUI introduces containerBackground for the system to decide when to draw background. It also automatically applies margin to widget so we may need to disable that

To update existing widgets, we can …

How to make tag flow layout using Layout protocol in SwiftUI

Issue #944

SwiftUI in iOS 16 supports Layout protocol to arrange subviews

We need to implement 2 methods

How to use hover annotation in Swift Charts

Issue #943

In this tutorial, we’ll learn how to use Swift Charts to visualize ranking data.

Screenshot 2023-08-18 at 11 48 28

We use default AxisMarks and AxisMarks to let Swift Charts interpolate x and y grid lines. For y axis, I want to have finer grain control over the …

How to scale image fill without affect layout in SwiftUI

Issue #939

Instead of letting the Image decide the size, we can put it as background or overlay. I use clipped and contentShape to avoid the fill image obscuring touch event

Color.clear
    .frame(height: 100)
    .overlay {
        AsyncImage(url: …

How to use AppIntents in iOS 16

Issue #930

AppIntents

Declare AppShortcutsProvider, note that appShortcuts uses @AppShortcutsBuilder syntax

import AppIntents

struct OurShortcutsProvider: AppShortcutsProvider {
    static var shortcutTileColor: ShortcutTileColor = .lightBlue …

How to press and hold button in SwiftUI

Issue #929

We can use ButtonStyleConfiguration to detect isPressed state

struct RecordButton: View {
    var body: some View {
        Button {
        
        } label: {
            Image(systemSymbol: .micFill)
        }
        .buttonStyle( …

How to use NavigationSplitView and NavigationStack in SwiftUI

Issue #924

Note

  • Navigation state needs to be in the container of NavigationSplitView for changes to propagate
  • Need to use WindowGroup for navigation bar to work

NavigationSplitView

the navigation split view coordinates with the List in its first …

How to style NavigationLink in macOS

Issue #923

NavigationLink on Mac applies the default button style. We can style it using ButtonStyle, here to use plain style we can just

NavigationLink(value: DetailRoute.books) {
    BooksView()
}
.buttonStyle(.plain)

SwiftUI EnvironmentValues

Issue #922

EnvironmentValues Views in SwiftUI can react to configuration information that they read from the environment using an Environment property wrapper

Updated for iOS 17

SwiftUI Environment values

How to make TextField Stepper in SwiftUI

Issue #921

Use HStack with TextField and a little extension

extension Binding where Value == Int {
    var toString: Binding<String> {
        Binding<String>(
            get: {
                "\(wrappedValue)"
            }, …

How to clear TextEditor background in SwiftUI

Issue #920

For iOS 16 and macOS 13.0

TextEditor(text: $text)
    .scrollContentBackground(.hidden)

For below, use [SwiftUI-Introspect](https://github.com/siteline/SwiftUI-Introspect)

TextEditor(text: $text)
    .instrospectTextView {
        $0. …

Learning Metal for SwiftUI

Issue #919

WWDC23 introduces lots of new additions to SwiftUI, notably Metal shader support with these modifiers

  • colorEffect: Returns a new view that applies shader to self as a filter effect on the color of each pixel.
  • layerEffect: Returns a new …

How to show view below title bar for macOS in SwiftUi

Issue #899

Use NSTitlebarAccessoryViewController

var titleBarAccessoryVC: NSTitlebarAccessoryViewController {
    let vc = NSTitlebarAccessoryViewController()
    let view = HStack {
        Spacer()
        Button {
            
        } label: { …

How to drag using DragGesture in SwiftUI

Issue #898

Change element position using either offset or position, and use DragGesture

Use GestureState to store the updating startDragLocation to keep the start location when drag begins, so we can add translation

struct MoveModifier: ViewModifier …

How to handle slow large dataset Picker when dragging in SwiftUI

Issue #897

During continuous events like dragging or TextField typing, and we have a Picker onscreen with large data set, it will slow down main thread.

One option is to explicitly conform that view to Equatable

struct FontPicker: View, Equatable { …

How to pass FocusState binding in SwiftUI

Issue #896

Use underscore _focus we get access to underlying FocusState object, but underscore _ is private to a View hence can’t be used in extension

If we want to pass FocusState to another View or in extension, we can pass its Binding

enum …

How to move reversed List in SwiftUI

Issue #895

Apply .move on reversed array

List(selection: $viewModel.selectedBook) {
    ForEach(viewModel.books.reversed()) { book in
        BookCell(book: book)
    }
    .onMove { source, dest in
        var reversed = Array(viewModel.books. …

How to set popoverPresentationController sourceView in SwiftUI

Issue #894

Use a UIView as source view and set it in background

class ViewModel {
    lazy var sourceView = UIView()
}

struct SourceView: UIViewRepresentable {
    let viewModel: ViewModel

    func makeUIView(context: Context) -> UIView { …

My favorite WWDC videos

Issue #891

Below are my favorite WWDC videos. My focus is to use SwiftUI to make useful apps with great UX. I don’t pay much attention to new frameworks as they come and go, but the underlying reasons and design principles are worth …

WWDC swiftui-lounge

Issue #890

In WWDC21, WWDC22 Apple provide a Slack channel https://wwdc22.slack.com/ for people to interact with Apple engineers in digital lounges. Here I note down some interesting Q&As

WWDC22

What’s the difference between a custom ViewModifier …

WWDC22 SwiftUI Q&A

Issue #890

Interesting SwiftUI Q&A during WWDC22

What’s the difference between a custom ViewModifier vs View extension

Q: What’s the difference between a custom ViewModifier (without DynamicProperty) that uses some built-in modifiers in …

What's new in SwiftUI iOS 16 at WWDC22

Issue #889

asda

What’s new in SwiftUI

New EnvironmentValues

abc

TextField inside Alert

abc

List uses UICollectionView

See gist https://gist.github.com/onmyway133/fc08111964984ef544a176a6e9806c18

abc

ButtonStyle composition

Screenshot 2022-06-09 at 10 25 30
Section("Hashtags") { …

How to use popover in SwiftUI

Issue #882

In SwiftUI, .popover shows as popover on Mac and iPad, but as .sheet on iPhone (compact size class)

We can use minWidth, minHeight to specify sizes on Mac and iPad. On iPhone, we can check and wrap it inside NavigationView. Setting …

How to select in List in SwiftUI

Issue #881

Specify optional value for List(selection:).

This keeps selection on macOS, but not on iPad. On iPad each row in the List needs to be NavigationLink, no need for .tag. The selection is not updated, need to manually update with onTapGesture …

How to allow multiple selection in List in SwiftUI

Issue #878

Note that

  • Explicit id is needed, although Book already conforms to Identifiable
  • selection needs a default value
class BookViewModel: ObservableObject {
    @Published var books: [Book] = []
    @Published var selectedBooks: Set<Book …

How to use ViewBuilder in SwiftUI

Issue #877

Over the course of making several SwiftUI apps, I’ve discovered quite a few hidden magic of SwiftUI that are quite fun.

Here are 6 interesting SwiftUI features in View Builder many don’t know are even possible 🤯

View protocol …

How to debounce TextField search in SwiftUI

Issue #876

Make a dedicate DebounceObject to debounce (or throttle). Then we can even observe with onChange on the debouncedText or just use it directly to sort

import Combine

public final class DebounceObject: ObservableObject {
    @Published var …

How to pop multiple level with NavigationView and NavigationLink in SwiftUI

Issue #858

Use isActive and isDetailLink(false)

Use Introspect

.introspectNavigationController { nav in
    self.nav = nav
}

Read more

How to show QR code in SwiftUI

Issue #855

Use CoreImage to generate QR image

import SwiftUI
import CoreImage.CIFilterBuiltins

struct QRView: View {
    let qrCode: String
    @State private var image: UIImage?

    var body: some View {
        ZStack {
            if let image = …

How to disable with ButtonStyle in SwiftUI

Issue #853

With ButtonStyle, the disabled modifier does not seem to work, we need to use allowsHitTesting.

import SwiftUI

struct ActionButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        HStack { …

How to use dynamic shape in SwiftUI

Issue #850

Erase with AnyShape

struct AnyShape: Shape {
    init<S: Shape>(_ wrapped: S) {
        innerPath = { rect in
            let path = wrapped.path(in: rect)
            return path
        }
    }

    func path(in rect: CGRect) -> …

How to use Picker with optional selection in SwiftUI

Issue #849

We need to explicitly specify optional in tag

extension AVCaptureDevice: Identifiable {
    public var id: String { uniqueID }
}

@State var device: AVCaptureDevice?

Picker("Camera", selection: $device) {
    ForEach(manager. …

How to scale system font size to support Dynamic Type

Issue #847

We should use Dynamic Font Type as much as possible, as per Typography guide and https://www.iosfontsizes.com/

But in case we have to use a specific font, we can scale it with UIFontMetrics

import SwiftUI
import UIKit

extension Font { …

How to round specific corner in SwiftUI

Issue #846

We use UIBezierPath with addArc to draw specific corner with different rounding values.

import SwiftUI

extension View {
    func clipCorners(
        topLeft: CGFloat = 0,
        bottomLeft: CGFloat = 0,
        topRight: CGFloat = 0, …

How to show suffix text in TextField in SwiftUI

Issue #845

Suppose we have struct Payment as the state, we declare custom Binding<String> that derives from our state.

struct Payment {
    var amount: Int = 0
}

To show our suffix view, we use .fixedSize(horizontal: true, vertical: false) to …

How to show currency symbol in TextField in SwiftUI

Issue #844

Use custom Binding and validate the text. In case of zero, return empty string to let TextField display placeholder

var textField: some View {
    let text = Binding<String>(
        get: {
            state.amount > 0 ? "$\( …

How to make multiline message text view in SwiftUI

Issue #843

This can be used in message bar input or some popover form. We use sizeThatFits to calculate the height so that it grow under certain height limit

import SwiftUI
import UIKit

struct MessageTextField: View {
    let placeholder: String …

How to read safe area insets in SwiftUI

Issue #842

Declare EnvironmentKey and read safeAreaInsets from key window in connectedScenes

struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets {
        UIApplication.shared.keyWindow?.safeAreaInsets.swiftUIInsets ?? …

How to make tab strip with enum cases in SwiftUI

Issue #841

Declare generic on RawRepresentable

import SwiftUI

struct TabStrip<T: RawRepresentable & Hashable>: View where T.RawValue == String {
    let values: [T]
    @Binding var selected: T

    var body: some View {
        ScrollView …

How to map Binding with optional value in SwiftUI

Issue #838

We can write our custom Binding

import SwiftUI

extension Binding where Value == Date? {
    func flatten(defaultValue: Date) -> Binding<Date> {
        Binding<Date>(
            get: { wrappedValue ?? defaultValue }, …

How to get view height in SwiftUI

Issue #837

I usually use GeometryReader in background to get size of view, and encapsulate it inside a ViewModifier

struct GetHeightModifier: ViewModifier {
    @Binding var height: CGFloat

    func body(content: Content) -> some View { …

How to prevent wheel Picker conflict with DragGesture in SwiftUI

Issue #836

If we have a Picker inside a View that has DragGesture, chances are when we scroll the wheel, the DragGesture is detected too

To prevent this, we can attach a dummy DragGesture to our Picker

Picker("", selection: $number) { …

How to make equal width buttons in SwiftUI

Issue #835

I usually define ButtonStyle to encapsulate common styles related to buttons. Here we specify .frame(maxWidth: .infinity) to let this button take the whole width as possible

struct MyActionButtonStyle: ButtonStyle {
    func makeBody( …

How to make bottom sheet in SwiftUI

Issue #834

In iOS 15, we can use UISheetPresentationController to show bottom sheet like native Maps app. But before that there’s no such built in bottom sheet in UIKit or SwiftUI.

We can start defining API for it. There are 3 ways to show …

How to bind to nested ObservableObject in SwiftUI

Issue #831

We can normally listen to sub ObservableObject by either listen to its objectWillChange or its Publisher

class SubModel: ObservableObject {
    @Published var count = 0
}

class AppModel: ObservableObject {
    @Published var submodel: …

How to structure navigation in SwiftUI apps

Issue #830

Since iOS 16, it is possible to define programmatic routes with `NavigationStack

I usually start by defining enum Route for all possible routes in the app. Note if your app is complex, you can define multiple Route type, each for different …

How to track contentSize and scroll offset for ScrollView in SwiftUI

Issue #829

Use PreferenceKey with a custom coordinateSpace to make our own TrackableScrollView. Note that the offset here is in reversed to contentOffset in normal UIScrollView

import SwiftUI

struct TrackableScrollView<Content: View>: View { …

How to focus TextField in SwiftUI

Issue #828

From iOS 15, FocusState

Use focused(_:) for single TextField, and focused(_:equals:) for multiple TextField

struct FormView: View {

    @FocusState private var isFocused: Bool
    @State private var name = ""

    var body: some …

How to use Button inside NavigationLink in SwiftUI

Issue #826

Use isActive binding

@State private var goesToDetail: Bool = false

NavigationLink(
    destination: DetailView(viewModel: viewModel),
    isActive: $goesToDetail) {
    Button(action: { goesToDetail = true }) {
        Text("Next" …

How to structure user state for App in SwiftUI

Issue #825

For many apps that require user authentication, a common practice is to define a shared UserManager with an optional User. This is convenient but it requires us to constantly unwrap and check that user

class UserManager {
    static let …

How to do NavigationLink programatically in SwiftUI

Issue #824

Use a custom NavigationLink with EmptyView as the background, this failable initializer accepts Binding of optional value. This works well as the destination are made lazily.

extension NavigationLink where Label == EmptyView {
    init …

How to make custom navigation bar in SwiftUI

Issue #823

Make atomic components and compose them. Firstly with NavigationBar that has custom leading and trailing content, there we can customize padding.

import SwiftUI

struct NavigationBar<Leading: View, Trailing: View>: View {
    @ …

How to convert NSEvent locationInWindow to window coordinate

Issue #822

Get active screen with mouse

func activeScreen() -> NSScreen? {
    let mouseLocation = NSEvent.mouseLocation
    let screens = NSScreen.screens
    let screenWithMouse = (screens.first { NSMouseInRect(mouseLocation, $0.frame, false) }) …

How to sync width for child views in SwiftUI

Issue #821

Suppose we have a 16:9 preview Image and we want the title Text to be the same width

First we need PreferenceKey to store and sync size

struct SizePreferenceKey: PreferenceKey {
    typealias Value = CGSize
    static var defaultValue: …

How to highlight link in Text in SwiftUI

Issue #820

Use NSDataDetector to detect links, and NSMutableAttributedString to mark link range. Then we enumerateAttributes and build our Text

Screenshot 2021-07-06 at 07 23 56
func attribute(string: String) -> Text {
    guard let detector = try? NSDataDetector(types: …

How to show custom context menu in SwiftUI

Issue #818

There’s a lot to do to imitate iOS ContextMenu look and feel

  • vibrancy blur background
  • haptics feedback
  • targeted view position
  • interaction dismiss gesture

For now here’s a rough implementation of a custom context menu where we …

How to declare View with ViewBuilder in SwiftUI

Issue #817

Thanks to resultBuilder and container type in Swift, the following are possible in SwiftUI

Local variable

struct ChartView {
    var body: some View {
        computation
    }

    @ViewBuilder
    var computation: some View {
        let …

How to make custom Menu in SwiftUI

Issue #816

SwiftUI supports Menu but the menu items only appear after the menu button is touched. We can initiate the look and feel of Menu with a custom implementation

Screenshot 2021-07-01 at 21 11 02
import SwiftUI

struct CustomMenu<Content: View>: View {
    @ViewBuilder …

How ObservableObject work in SwiftUI

Issue #815

When ever a property marked with @Published change, ObservableObject will emit objectWillChange.send hence telling the View that observes it to reinvalidate.

In WWDC 2021 session Discover concurrency in SwiftUI they mention how …

How to cancel vertical scrolling on paging TabView in SwiftUI

Issue #814

From iOS 14, TabView has the PageTabViewStyle that turns TabView into the equivalent UIPageViewController.

We can of course implement our own Pager but the simple DragGesture does not bring the true experience of a paging UIScrollView or …

How to make carousel pager view in SwiftUI

Issue #812

Use GeometryReader to set width and a DragGesture on LazyVStack

CarouselView(
    pageCount: images.count,
    currentIndex: $selectedImageIndex
) {
    ForEach(0 ..< images) { image in
        // AsyncImage
    }
}
struct CarouselView …

How to show context menu with custom preview in SwiftUI

Issue #809

Add a hidden overlay UIContextMenuInteraction. Provide preview in previewProvider and actions in actionProvider. Use @ViewBuilder to make declaring preview easy.

extension View {
    func contextMenuWithPreview<Content: View>( …

How to login with Apple in SwiftUI

Issue #808

Make SignInWithAppleButton

Wrap ASAuthorizationAppleIDButton inside UIViewRepresentable

import SwiftUI
import UIKit
import AuthenticationServices

struct SignInWithAppleButton: View {
    @Environment(\.colorScheme)
    private var …

How to use SwiftGen and LocalizedStringKey in SwiftUI

Issue #798

swiftgen.yml

strings:
  inputs: PastePal/Resources/Localizable/en.lproj
  outputs:
    - templatePath: swiftgen-swiftui-template.stencil
      output: PastePal/Resources/Strings.swift

Template from …

How to use ForEach with indices in SwiftUI

Issue #796

One seemingly obvious way to use ForEach on array with indices is using enumerated

struct Book: Hashable, Identifiable {
    let id: UUID
    let name: String
}

struct BooksView: View {
    let books: [Book]

    var body: some View { …

How to convert from paid to freemium in SwiftUI with RevenueCat

Issue #794

I’ve been distributing my apps PastePal and Push Hero as a paid upfront apps on Appstore. I’ve quickly come to realize the importance of trials since many have requested a tryout before purchasing.

Manual sending out trials …

How to use View protocol in SwiftUI

Issue #791

SwiftUI has View protocol which represents part of your app’s user interface and provides modifiers that you use to configure views.

You create custom views by declaring types that conform to the View protocol. Implement the required …

How to manage WindowGroup in SwiftUI for macOS

Issue #789

Using WindowGroup

New in SwiftUI 2.0 for iOS 14 and macOS 11.0 is WindwGroup which is used in App protocol. WindowGroup is ideal for document based applications where you can open multiple windows for different content or files. For …

How to use Core Data

Issue #785

Core Data

Calling mergeChanges on a managed object context will automatically refresh any managed objects that have changed. This ensures that your context always contains all the latest …

How to force resolve Swift Package in Xcode

Issue #784

Every time I switch git branches, SPM packages seem to be invalidated and Xcode does not fetch again, no matter how many times I reopen. Running xcodebuild -resolvePackageDependencies does fetch but Xcode does not recognize the resolved …

How to listen to Published outside of SwiftUI view

Issue #782

Use $ to access Publisher

final class Store: ObservableObject {
    @Published var showsSideWindow: Bool = false
}
var anyCancellables = Set<AnyCancellable>()

store.$showsSideWindow
    .removeDuplicates()
    .throttle(for: 0.2, …

How to build container view in SwiftUI

Issue #780

To make a container view that accepts child content, we use ViewBuilder

struct ContainerView<Content: View>: View {
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    } …

How to tune performance with ButtonBehavior in SwiftUI

Issue #779

With Xcode 12.4, macOS 11.0 app. Every time we switch the system dark and light mode, the CPU goes up to 100%. Instruments show that there’s an increasing number of ButtonBehavior

Screenshot 2021-02-24 at 10 12 05

Suspect State in a row in LazyVStack

Every cell has …

How to make simple search bar in SwiftUI

Issue #776

We need to use a custom Binding to trigger onChange as onEditingChanged is only called when the user selects the textField, and onCommit is only called when return or done button on keyboard is tapped.

import UIKit
import SwiftUI
import …

How to add home screen quick action in SwiftUI

Issue #774

Start by defining your quick actions. You can use UIApplicationShortcutIcon(type:) for predefined icons, or use UIApplicationShortcutIcon(systemImageName:) for SFSymbol

enum QuickAction: String {
    case readPasteboard
    case clear …

How to use EquatableView in SwiftUI

Issue #773

From John Harper ’s tweet

SwiftUI assumes any Equatable.== is a true equality check, so for POD views it compares each field directly instead (via reflection). For non-POD views it prefers the view’s == but falls back to its own …

How to add new property in Codable struct in SwiftUI

Issue #772

I use Codable structs in my apps for preferences, and bind them to SwiftUI views. If we add new properties to existing Codable, it can’t decode with old saved json as we require new properties. We can either do cutom decoding with …

How to handle escape in NSTextField in SwiftUI

Issue #770

Handle cancelOperation somewhere up in responder chain

class MyWindow: NSWindow {
    let keyHandler = KeyHandler()

    override func cancelOperation(_ sender: Any?) {
        super.cancelOperation(sender)
        keyHandler.onEvent(.esc) …

How to fit ScrollView to content in SwiftUI

Issue #769

If we place ScrollView inside HStack or VStack, it takes all remaining space. To fit ScrollView to its content, we need to get its content size and constrain ScrollView size.

Use a GeometryReader as Scrollview content background, and get …

How to show multiple popover in SwiftUI

Issue #765

In SwiftUI currently, it’s not possible to attach multiple .popover to the same View. But we can use condition to show different content

struct ClipboardCell: View {
    enum PopoverStyle {
        case raw
        case preview
    } …

How to handle keyDown in SwiftUI for macOS

Issue #764

Use a custom KeyAwareView that uses an NSView that checks for keyDown method. In case we can’t handle certain keys, call super.keyDown(with: event)

import SwiftUI
import KeyboardShortcuts

struct KeyAwareView: NSViewRepresentable { …

How to extend custom View in SwiftUI

Issue #763

I usually break down a big struct into smaller views and extensions. For example I have a ClipboardCell that has a lot of onReceive so I want to move these to another component.

One way to do that is to extend ClipboardCell

struct …

How to use ScrollViewReader in SwiftUI

Issue #761

Explicitly specify id

ScrollView {
    ScrollViewReader { proxy in
        LazyVStack(spacing: 10) {
            ForEach(items) { item in
                Cell(item: item)
                    .id(item.id)
            }
        }
        . …

How to fix overlapped navigation titles in SwiftUI

Issue #756

extension NavigationLink {
    func fixOverlap() -> AnyView {
        if UIDevice.current.userInterfaceIdiom == .phone {
            return self.isDetailLink(false).erase()
        } else {
            return self.erase()
        } …

How to make popup button in SwiftUI for macOS

Issue #748

There is said to be PopUpButtonPickerStyle and MenuPickerStyle but these don’t seem to work.

There’s Menu button it shows a dropdown style. We fake it by fading this and overlay with a button. allowsHitTesting does not work, …

How to use UITextView in SwiftUI

Issue #747

Need to use Coordinator conforming to UITextViewDelegate to apply changes back to Binding

import SwiftUI
import UIKit

struct MyTextView: UIViewRepresentable {
    @Binding
    var text: String

    final class Coordinator: NSObject, …

How to check app going to background in SwiftUI

Issue #746

From iOS 13, the default is to support multiple scene, so the the old UIApplicationDelegate lifecycle does not work. Double check your Info.plist for UIApplicationSceneManifest key

<key>UIApplicationSceneManifest</key> …

How to use selection in List in SwiftUI

Issue #745

I used to use selection with Binding where wrappedValue is optional, together with tag in SwiftUI for macOS, and it shows current selection

@Binding
var selection: Tag? = .all

List(section: $selection) {
    Text("All")
         . …

How to make tiled image in SwiftUI

Issue #737

Use resizingMode of .tile with a tile image from https://www.transparenttextures.com/

Image("transparentTile")
    .resizable(capInsets: .init(), resizingMode: .tile)
    .scaleEffect(2)
    .aspectRatio(contentMode: .fit)
    . …

How to use WebView in SwiftUI

Issue #736

struct MyWebView: NSViewRepresentable {
    let url: URL
    @Binding
    var isLoading: Bool

    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }

    func makeNSView(context: Context) -> WKWebView { …

How to use GeometryReader in SwiftUI

Issue #735

From my previous post How to use flexible frame in SwiftUI we know that certain views have different frame behaviors. 2 of them are .overlay and GeometryReader that takes up whole size proposed by parent.

By default GeometryReader takes up …

How to use flexible frame in SwiftUI

Issue #734

In SwiftUI there are fixed frame and flexible frame modifiers.

Fixed frame Positions this view within an invisible frame with the specified size.

Use this method to specify a fixed size for a view’s width, height, or both. If you only …

How to make view appear with delay in SwiftUI

Issue #731

Sometimes we don’t want to show progress view right away

HUDProgressView()
    .transition(
        AnyTransition.asymmetric(
            insertion: AnyTransition.opacity.animation(Animation.default.delay(1)),
            removal: …

How to make attributed string Text in SwiftUI for macOS

Issue #730

Use NSTextField with maximumNumberOfLines

import AppKit
import SwiftUI

struct AttributedText: NSViewRepresentable {

    let attributedString: NSAttributedString

    init(_ attributedString: NSAttributedString) {
        self. …

How to make visual effect blur in SwiftUI for macOS

Issue #724

We can use .blur modifier, but with VisualEffectView gives us more options for material and blending mode.

public struct VisualEffectView: NSViewRepresentable {
    let material: NSVisualEffectView.Material
    let blendingMode: …

How to make simple HUD in SwiftUI

Issue #723

Use @ViewBuilder to build dynamic content for our HUD. For blur effect, here I use NSVisualEffectView, but we can use .blur modifier also

struct HUD<Content>: View where Content: View {
    let content: () -> Content

    init(@ …

How to instrument SwiftUI app

Issue #722

With Xcode 12, we can fire up Instrument to profile our app. Select SwiftUI template

Screenshot 2020-12-26 at 00 02 03

There are many profiles in that template, I find SwiftUI and Time Profile very useful. Here’s the profile I run for my app PastePal

SwiftUI View …

How to show image and text in menu item in SwiftUI for macOS

Issue #719

From SwiftUI 2 for macOS 11.0, we have access to Menu for creating menu and submenu. Usually we use Button for interactive menu items and Text for disabled menu items.

The easy way to customize menu with image is to call Menu with content …

How to make sharing menu in SwiftUI for macOS

Issue #718

Use NSSharingService.sharingServices(forItems:) with an array of one empty string gives a list of sharing items. There we show image and title of each menu item.

We should cache sharing items as that can cause performance issue

import …

How to make stepper with plus and minus buttons in SwiftUI for macOS

Issue #717

Try to use predefined system colors in Human Interface Guidelines for macOS

Here we use this color unemphasizedSelectedTextBackgroundColor for button background

Screenshot 2020-12-21 at 06 24 16
HStack(spacing: 1) {
    makeUnderListButton(action: {}, icon: .plus) …

How to fix Picker not showing selection in SwiftUI

Issue #716

I have an enum that conforms to CaseIterable that I want to show in Picker

enum Position: String, Codable, CaseIterable, Identifiable {
    var id: String { rawValue }
    case left
    case right
    case bottom
    case top
}

Picker( …

How to do didSet for State and Binding in SwiftUI

Issue #714

Below is an example of a parent ContentView with State and a child Sidebar with a Binding.

The didSet is only called for the property that is changed.

When we click Button in ContentView, that changes State property, so only the didSet in …

How to programatically select row in List in SwiftUI

Issue #711

List has a selection parameter where we can pass selection binding. As we can see here selection is of type optional Binding<Set<SelectionValue>>? where SelectionValue is any thing conforming to Hasable

@available(iOS 13.0, …

How to show sidebar in SwiftUI for macOS

Issue #710

Starting from macOS 11, we can use List with SidebarListStyle inside NavigationView to declare master detail view. The SidebarListStyle makes list translucent. It automatically handles selection and marks selected row in list with accent …

How to disable NSTextView in SwiftUI

Issue #702

The trick is to use an overlay

MessageTextView(text: $input.message)
    .overlay(obscure)

var obscure: AnyView {
    if store.pricingPlan.isPro {
        return EmptyView().erase()
    } else {
        return Color.black.opacity(0.01). …

How to use nested ObservableObject in SwiftUI

Issue #694

I usually structure my app to have 1 main ObservableObject called Store with multiple properties in it.

final class Store: ObservableObject {
    @Published var pricingPlan: PricingPlan()
    @Published var preferences: Preferences()
} …

How to check dark mode with color scheme in SwiftUI

Issue #692

Use colorScheme environment, for now it has 2 cases dark and light

struct MainView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text(colorScheme == .dark ? "Dark Mode" : "Light …

How to make full size content view in SwiftUI for macOS

Issue #689

func applicationDidFinishLaunching(_ aNotification: Notification) {
    // extend to title bar
    let contentView = ContentView()
        // .padding(.top, 24) // can padding to give some space
        .edgesIgnoringSafeArea(.top)

    // …

How to override styles in SwiftUI

Issue #688

In the app I’m working on Elegant Converter, I usually like preset theme with a custom background color and a matching foreground color.

Thanks to SwiftUI style cascading, I can just declare in root MainView and it will be inherited …

How to use CoreData safely

Issue #686

I now use Core Data more often now. Here is how I usually use it, for example in Push Hero

From iOS 10 and macOS 10.12, NSPersistentContainer that simplifies Core Data setup quite a lot. I usually use 1 NSPersistentContainer and its …

How to pass ObservedObject as parameter in SwiftUI

Issue #685

Since we have custom init in ChildView to manually set a State, we need to pass ObservedObject. In the ParentView, use underscore _ to access property wrapper type.

struct ChildView: View {
    @ObservedObject
    var store: Store

    @ …

How to do equal width in SwiftUI

Issue #684

In SwiftUI, specifying maxWidth as .infinity means taking the whole available width of the container. If many children ask for max width, then they will be divided equally. This is similar to weight in LinearLayout in Android or css …

How to style multiline Text in SwiftUI for macOS

Issue #681

Only need to specify fixedSize on text to preserve ideal height.

The maximum number of lines is 1 if the value is less than 1. If the value is nil, the text uses as many lines as required. The default is nil.

Text(longText)
    .lineLimit …

How to clear List background color in SwiftUI for macOS

Issue #680

For List in SwiftUI for macOS, it has default background color because of the enclosing NSScrollView via NSTableView that List uses under the hood. Using listRowBackground also gives no effect

The solution is to use a library like …

How to avoid reduced opacity when hiding view with animation in SwiftUI

Issue #679

While redesigning UI for my app Push Hero, I ended up with an accordion style to toggle section.

Screenshot 2020-10-01 at 06 58 33

It worked great so far, but after 1 collapsing, all image and text views have reduced opacity. This does not happen for other elements like …

How to dynamically add items to VStack from list in SwiftUI

Issue #678

Use enumerated to get index so we can assign to item in list. Here is how I show list of device tokens in my app Push Hero

private var textViews: some View {
    let withIndex = input.deviceTokens.enumerated().map({ $0 })
    let binding: …

How to unwrap Binding with Optional in SwiftUI

Issue #677

The quick way to add new properties without breaking current saved Codable is to declare them as optional. For example if you use EasyStash library to save and load Codable models.

import SwiftUI

struct Input: Codable {
    var bundleId: …

How to make custom toggle in SwiftUI

Issue #676

I’ve used the default SwiftUI to achieve the 2 tab views in SwiftUI. It adds a default box around the content and also opinionated paddings. For now on light mode on macOS, the unselected tab has wrong colors.

The way to solve this …

How to use Binding in function in Swift

Issue #675

Use wrappedValue to get the underlying value that Binding contains

extension View {
    func addOverlay(shows: Binding<Bool>) -> some View {
        HStack {
            self
            Spacer()
        }
        .overlay( …

How to use HSplitView to define 3 panes view in SwiftUI for macOS

Issue #674

Specify minWidth to ensure miminum width, and use .layoutPriority(1) for the most important pane.

import SwiftUI

struct MainView: View {
    @EnvironmentObject var store: Store

    var body: some View {
        HSplitView { …

How to make switch statement in SwiftUI

Issue #656

Lately I’ve been challenging myself to declare switch statement in SwiftUI, or in a more generalized way, execute any anonymous function that can return a View

Use Switch and Case views

Note that this approach does not work yet, as …

How to conditionally apply modifier in SwiftUI

Issue #633

Use autoclosure and AnyView

@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public extension View {
    func applyIf<T: View>(_ condition: @autoclosure () -> Bool, apply: (Self) -> T) -> AnyView {
        if …

How to toggle with animation in SwiftUI

Issue #632

Use Group

private func makeHeader() -> some View {
    Group {
        if showsSearch {
            SearchView(
                onSearch: onSearch
            )
            .transition(.move(edge: .leading))
        } else { …

How to show context popover from SwiftUI for macOS

Issue #630

For SwiftUI app using NSPopover, to show context popover menu, we can ask for windows array, get the _NSPopoverWindow and calculate the position. Note that origin of macOS screen is bottom left

(lldb) po NSApp.windows
▿ 2 elements
  - 0 : …

How to make segmented control in SwiftUI for macOS

Issue #629

Use Picker with SegmentedPickerStyle.

Picker(selection: $preferenceManager.preference.display, label: EmptyView()) {
    Image("grid")
        .resizable()
    .padding()
        .tag(0)
    Image("list")
        .resizable …

How to trigger onAppear in SwiftUI for macOS

Issue #626

SwiftUI does not trigger onAppear and onDisappear like we expect. We can use NSView to trigger

import SwiftUI

struct AppearAware: NSViewRepresentable {
    var onAppear: () -> Void

    func makeNSView(context: …

How to force refresh in ForEach in SwiftUI for macOS

Issue #625

For some strange reasons, content inside ForEach does not update with changes in Core Data NSManagedObject. The workaround is to introduce salt, like UUID just to make state change

struct NoteRow: View {
    let note: Note
    let id: UUID …

How to force FetchRequest update in SwiftUI

Issue #623

Listen to context changes notification and change SwiftUI View state

let changes = [NSDeletedObjectsKey: ids]
NSManagedObjectContext.mergeChanges(
    fromRemoteContextSave: changes,
    into: [context]
)
try context.save()

struct …

How to batch delete in Core Data

Issue #622

Read Implementing Batch Deletes

If the entities that are being deleted are not loaded into memory, there is no need to update your application after the NSBatchDeleteRequest has been executed. However, if you are deleting objects in the …

How to update FetchRequest with predicate in SwiftUI

Issue #621

Make subview that accepts FetchRequest. Trigger search by setting property

struct SideView: View {
    @Environment(\.managedObjectContext)
    var context

    @State var search: Search?

    var body: some View {
        VStack(alignment …

How to make TextField focus in SwiftUI for macOS

Issue #620

For NSWindow having levelother than .normal, need to override key and main property to allow TextField to be focusable

class FocusWindow: NSWindow {
    override var canBecomeKey: Bool  { true }
    override var canBecomeMain: Bool { …

How to show popover for item in ForEach in SwiftUI

Issue #618

Create custom Binding

List {
    ForEach(self.items) { (item: item) in
        ItemRowView(item: item)
            .popover(isPresented: self.makeIsPresented(item: item)) {
                ItemDetailView(item: item)
            }
    }
} …

How to make translucent SwiftUI List in macOS

Issue #615

List {
    ForEach(books) { (book: Book) in
        BookRow(book: book)
    }
}
.listStyle(SidebarListStyle())  

How to make tab view in SwiftUI

Issue #614

struct MyTabView: View {
    @EnvironmentObject
    var preferenceManager: PreferenceManager

    var body: some View {
        VOrH(isVertical: preferenceManager.preference.position.isVertical) {
            OneTabView(image: …

How to return VStack or HStack in SwiftUI

Issue #613

struct VOrH<Content>: View where Content: View {
    let isVertical: Bool
    let content: () -> Content

    init(isVertical: Bool, @ViewBuilder content: @escaping () -> Content) {
        self.isVertical = isVertical …

How to present NSWindow modally

Issue #612

Use runModal

This method runs a modal event loop for the specified window synchronously. It displays the specified window, makes it key, starts the run loop, and processes events for that window. (You do not need to show the window …

How to use visual effect view in NSWindow

Issue #610

Set NSVisualEffectView as contentView of NSWindow, and our main view as subview of it. Remember to set frame or autoresizing mask as non-direct content view does not get full size as the window

let mainView = MainView()
    .environment(\. …

How to edit selected item in list in SwiftUI

Issue #605

I use custom TextView in a master detail application.

import SwiftUI

struct TextView: NSViewRepresentable {
    @Binding var text: String

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeNSView …

How to log in SwiftUI

Issue #604

I see that the modifier needs to do something on the content, otherwise it is not getting called! This logs on the modifier, when the View is created. A View won’t be recreated unless necessary

struct LogModifier: ViewModifier { …

How to avoid pitfalls in SwiftUI

Issue #602

Identify by unique id

ForEach(store.blogs.enumerated().map({ $0 }), id: \.element.id) { index, blog in

}
```

## 

How to use TabView with enum in SwiftUI

Issue #599

Specify tag

enum Authentication: Int, Codable {
    case key
    case certificate
}


TabView(selection: $authentication) {
    KeyAuthenticationView()
        .tabItem {
            Text("🔑 Key")
        }
        .tag( …

How to build SwiftUI style UICollectionView data source in Swift

Issue #598

It’s hard to see any iOS app which don’t use UITableView or UICollectionView, as they are the basic and important foundation to represent data. UICollectionView is very basic to use, yet a bit tedious for common use cases, but …

How to make round border in SwiftUI

Issue #597

TextView(font: R.font.text!, lineCount: nil, text: $text, isFocus: $isFocus)
.padding(8)
.background(R.color.inputBackground)
.cornerRadius(10)
.overlay(
    RoundedRectangle(cornerRadius: 10)
        .stroke(isFocus ? R.color. …

How to change background color in List in SwiftUI for macOS

Issue #595

SwiftUI uses ListCoreScrollView and ListCoreClipView under the hood. For now the workaround, is to avoid using List

List {
    ForEach
}

use

VStack {
    ForEach
}

How to add drag and drop in SwiftUI

Issue #594

In some case, we should not use base type like UTType.text but to be more specific like UTType.utf8PlainText

import UniformTypeIdentifiers

var dropTypes: [UTType] {
    [
        .fileURL,
        .url,
        .utf8PlainText,
        . …

How to make radio button group in SwiftUI

Issue #592

Use picker with Radio style

Hard to customize

Picker(selection: Binding<Bool>.constant(true), label: EmptyView()) {
    Text("Production").tag(0)
    Text("Sandbox").tag(1)
}.pickerStyle(RadioGroupPickerStyle())

Use …

How to make borderless material NSTextField in SwiftUI for macOS

Issue #590

Use custom NSTextField as it is hard to customize TextFieldStyle

import SwiftUI

struct MaterialTextField: View {
    let placeholder: String
    @Binding var text: String
    @State var isFocus: Bool = false

    var body: some View { …

How to show localized text in SwiftUI

Issue #533

struct ContentView: View {
    @Environment(\.locale) var locale: Locale

    var body: some View {
        VStack {
            Text(LocalizedStringKey("hello"))
                .font(.largeTitle)
            Text(flag(from: …

How to use ForEach with ScrollView in SwiftUI

Issue #517

Use ScrollView -> VStack -> ForEach -> Content

struct SearchScreen: View {
    @State var searchObjects: [SearchObject] = [
        SearchObject(name: "By name", search: { CountryManager.shared.search(byName: $0) }), …

How to modify data inside array in SwiftUI

Issue #516

Suppose we have an array of SearchObject, and user can enter search query into text property.

class SearchObject: ObservableObject {
    let name: String
    let search: (String) -> [Country]
    var text: String = ""

    init( …

How to use index in SwiftUI list

Issue #515

Use enumerated and id: \.element.name

struct CountriesView: View {
    let countries: [Country]

    var body: some View {
        let withIndex = countries.enumerated().map({ $0 })

        return List(withIndex, id: \.element.name) { …

How to use objectWillChange in Combine

Issue #513

A publisher that emits before the object has changed

Use workaround DispatchQueue to wait another run loop to access newValue

.onReceive(store.objectWillChange, perform: {
    DispatchQueue.main.async {
        self.reload()
    }
}) …

How to show list with section in SwiftUI

Issue #511

struct CountriesView: View {
    let groups: [Group]

    init(countries: [Country]) {
        self.groups = CountryManager.shared.groups(countries: countries)
    }

    var body: some View {
        List {
            ForEach(groups) { …

How to make full width list row in SwiftUI

Issue #508

We need to use frame(minWidth: 0, maxWidth: .infinity, alignment: .leading). Note that order is important, and padding should be first, and background after frame to apply color to the entire frame

struct BooksScreen: View {
    @ …

How to make full screen TabView in SwiftUI

Issue #507

View extends to the bottom, but not to the notch. We need to add .edgesIgnoringSafeArea(.top) to our TabView to tell TabView to extend all the way to the top.

Note that if we use edgesIgnoringSafeArea(.all) then TabView ’s bar will …

How to fix unable to infer complex closure return type in SwiftUI

Issue #505

Make sure all String are passed into Text, not Optional<String>

VStack {
    Text(data.title)
    Text(data.description!)
    Text(data.text!)
}

How to make simple Redux for SwiftUI

Issue #502

Mutation is used to mutate state synchronously. Action is like intent, either from app or from user action. Action maps to Mutation in form of Publisher to work with async action, similar to redux-observable

AnyReducer is a type erasure …

How to get Binding via dollar prefix in SwiftUI

Issue #488

The dollar is not a prefix, it seems to be a generated code for property wrapper, and each kind of property wrapper can determine which value it return via this dollar sign

State and ObservedObject are popular property wrappers in SwiftUI …

How to modify state from state in SwiftUI

Issue #487

In case we have to modify state when another state is known, we can encapsulate all those states in ObservableObject and use onReceive to check the state we want to act on.

See code Avengers

If we were to modify state from within body …

How to show loading indicator in SwiftUI

Issue #486

import SwiftUI

struct ActivityIndicator: UIViewRepresentable {
    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style

    func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> …

How to show image picker in SwiftUI

Issue #485

The easiest way to show image picker in iOS is to use UIImagePickerController, and we can bridge that to SwiftUI via UIViewControllerRepresentable

First attempt, use Environment

We conform to UIViewControllerRepresentable and make a …

How to use array of strings in ForEach in SwiftUI

Issue #483

Every item in list must be uniquely identifiable

List {
    ForEach(books, id: \.bookId) { book in
        NavigationLink(destination:
            BookView(book: book)
                .navigationBarTitle(book.name)
        ) { …

How to make multiline Text in SwiftUI in watchOS

Issue #482

lineLimit does not seem to work, use fixedSize instead

Fixes this view at its ideal size.

A view that fixes this view at its ideal size in the dimensions given in fixedDimensions.

extension Text {
    func styleText() -> some View { …

How to reload data without using onAppear in SwiftUI in watchOS

Issue #468

From onAppeear

Adds an action to perform when the view appears.

In theory, this should be triggered every time this view appears. But in practice, it is only called when it is pushed on navigation stack, not when we return to it.

So if …

How to use EnvironmentObject in SwiftUI for watchOS

Issue #467

Declare top dependencies in ExtensionDelegate

class ExtensionDelegate: NSObject, WKExtensionDelegate {
    let storeContainer = StoreContainer()

    func applicationDidEnterBackground() {
        storeContainer.save()
    }
}

Reference …

How to make container view in SwiftUI

Issue #450

Following the signatures of ScrollView and Group, we can create our own container

public struct ScrollView<Content> : View where Content : View {

    /// The content of the scroll view.
    public var content: Content

}
extension …

How to show web content as QR code in SwiftUI in watchOS

Issue #449

WatchKit does not have Web component, despite the fact that we can view web content

A workaround is to show url as QR code

import SwiftUI

struct QRCodeView: View {
    let …

How to load remote image in SwiftUI

Issue #448

Use ObservableObject and onReceive to receive event. URLSession.dataTask reports in background queue, so need to .receive(on: RunLoop.main) to receive events on main queue.

For better dependency injection, need to use ImageLoader from …

How to do navigation in SwiftUI in watchOS

Issue #447

NavigationView is not available on WatchKit, but we can just use NavigationLink

List(services.map({ AnyService($0) })) { anyService in
    NavigationLink(destination:
        ItemsView(service: anyService.service)
            . …

How to use protocol in List in SwiftUI

Issue #446

Suppose we have Service protocol, and want to use in List

protocol Service {
    var name: String { get }
}
struct MainView: View {
    let services = [
        Car()
        Plane()
    ]

    var body: some View {
        List(services) …