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鈥檚 width, height, or both. If you only specify one of the dimensions, the resulting view assumes this view鈥檚 sizing behavior in the other dimension. VStack { Ellipse() .fill(Color.purple) .frame(width: 200, height: 100) Ellipse() ....

January 1, 2021 路 7 min 路 Khoa Pham

How to make view appear with delay in SwiftUI

Issue #731 Sometimes we don鈥檛 want to show progress view right away HUDProgressView() .transition( AnyTransition.asymmetric( insertion: AnyTransition.opacity.animation(Animation.default.delay(1)), removal: AnyTransition.opacity) )

December 31, 2020 路 1 min 路 Khoa Pham

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.attributedString = attributedString } func makeNSView(context: Context) -> NSTextField { let textField = NSTextField() textField.lineBreakMode = .byClipping textField.maximumNumberOfLines = 0 textField.isBordered = false return textField } func updateNSView(_ nsView: NSTextField, context: Context) { nsView.attributedStringValue = attributedString } } TextField has problem with wrapping, we can use TextView struct AttributedTextView: NSViewRepresentable { typealias NSViewType = NSScrollView let attributedText: NSAttributedString?...

December 31, 2020 路 1 min 路 Khoa Pham

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: NSVisualEffectView.BlendingMode public init( material: NSVisualEffectView.Material = .contentBackground, blendingMode: NSVisualEffectView.BlendingMode = .withinWindow ) { self.material = material self.blendingMode = blendingMode } public func makeNSView(context: Context) -> NSVisualEffectView { let visualEffectView = NSVisualEffectView() visualEffectView.material = material visualEffectView.blendingMode = blendingMode visualEffectView.state = NSVisualEffectView.State.active return visualEffectView } public func updateNSView(_ visualEffectView: NSVisualEffectView, context: Context) { visualEffectView....

December 26, 2020 路 1 min 路 Khoa Pham

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(@ViewBuilder content: @escaping () -> Content) { self.content = content } var body: some View { content() .frame(width: 80, height: 80) .background( VisualEffectView(material: .hudWindow) .clipShape(RoundedRectangle(cornerRadius: 12)) .shadow(color: Color.black.opacity(0.22), radius: 12, x: 0, y: 5) ) } } Then we can make some wrappers for information and progress HUD...

December 26, 2020 路 1 min 路 Khoa Pham

How to instrument SwiftUI app

Issue #722 With Xcode 12, we can fire up Instrument to profile our app. Select SwiftUI template There are many profiles in that template, I find SwiftUI and Time Profile very useful. Here鈥檚 the profile I run for my app PastePal SwiftUI View Body This shows how many instance of View with body invocation are there, both for SwiftUI views and our app views Taking a look at SwiftUI profile, it shows that ClipboardCell is taking most of the time, here over 7 seconds...

December 25, 2020 路 2 min 路 Khoa Pham

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 and label. Pay attention to how we use Button and Label inside Content to create interactive menu items Menu( content: { ForEach(collections) { collection in Button(action: {) { Label(collection....

December 23, 2020 路 1 min 路 Khoa Pham

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 SwiftUI import AppKit import EasySwiftUI extension NSSharingService { private static let items = NSSharingService.sharingServices(forItems: [""]) static func submenu(text: String) -> some View { return Menu( content: { ForEach(items, id: \.title) { item in Button(action: { item....

December 23, 2020 路 1 min 路 Khoa Pham

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 HStack(spacing: 1) { makeUnderListButton(action: {}, icon: .plus) makeUnderListButton(action: {}, icon: .minus) } .background(Color(NSColor.unemphasizedSelectedTextBackgroundColor)) .cornerRadius(4) func makeUnderListButton(action: @escaping () -> Void, icon: AwesomeIcon) -> some View { Button(action: action) { Text(icon.rawValue) .font(.awesome(style: .solid, size: 14)) } .buttonStyle(HighlightButtonStyle(h: 8, v: 6, cornerRadius: 4)) } Another thing is List, where we have selected and alternative background colors....

December 21, 2020 路 1 min 路 Khoa Pham

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(selection: $preference.position, label: Text("Position")) { ForEach(Preference.Position.allCases) { position in Text(position.rawValue) } } It compiles and runs just fine, but Picker does not show current selection regardless of any Picker style I choose....

December 20, 2020 路 2 min 路 Khoa Pham

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 ContentView is called When we click Button in Sidebar, that changes Binding property, so only the didSet in Sidebar is called enum Tag: String { case all case settings } struct ContentView: View { @State private var tag: Tag = ....

December 16, 2020 路 2 min 路 Khoa Pham

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, macOS 10.15, tvOS 13.0, watchOS 6.0, *) public struct List<SelectionValue, Content> : View where SelectionValue : Hashable, Content : View { @available(watchOS, unavailable) public init(selection: Binding<Set<SelectionValue>>?, @ViewBuilder content: () -> Content) So we can programatically control selection by tagging row with our own Tag...

December 13, 2020 路 1 min 路 Khoa Pham

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 color. struct MainView: some View { var body: some View { NavigationView { sidebar ContentView() } } private var sidebar: some View { List { Group { Text("Categories") .foregroundColor(.gray) ForEach(categories) { category in NavigationLink(destination: ContentView(category: category)) { Label(category....

December 13, 2020 路 1 min 路 Khoa Pham

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).erase() } }

November 27, 2020 路 1 min 路 Khoa Pham

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() } struct Preferences { var opensAtLogin: Bool = true } final class PricingPlan: ObservableObject { @Published var isPro: Bool = true } SwiftUI for now does not work with nested ObservableObject, so if I pass Store to PricingView, changes in PricingPlan does not trigger view update in PricingView....

November 14, 2020 路 1 min 路 Khoa Pham

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 Mode") } }

November 10, 2020 路 1 min 路 Khoa Pham

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) // specify fullSizeContentView window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 800, height: 600), styleMask: [.titled, .closable, .miniaturizable, .texturedBackground, .resizable, .fullSizeContentView], backing: .buffered, defer: false ) window.center() window.setFrameAutosaveName("My App") // window.title = ... // no title // window.toolbar = NSToolbar() // use toolbar if wanted....

November 3, 2020 路 1 min 路 Khoa Pham

How to override styles in SwiftUI

Issue #688 In the app I鈥檓 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 down the view hierachy. struct MainView: View { var body: some View { HSplitView { ListView() RightView() } .foregroundColor(R.color.text) .background(R.color.background) } } This works great regardless of system light or dark mode, but in light mode it does not look good, as my designed theme is similar to dark mode....

October 31, 2020 路 2 min 路 Khoa Pham

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 viewContext together with newBackgroundContext attached to that NSPersistentContainer In Core Data, each context has a queue, except for viewContext using the DispatchQueue.main, and each NSManagedObject retrieved from 1 context is supposed to use within that context queue only, except for objectId property....

October 25, 2020 路 2 min 路 Khoa Pham

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 @State private var selectedTask: AnyTask init(store: ObservedObject<Store>) { _selectedTask = State(initialValue: tasks.first!) _store = store } } struct ParentView: View { @ObservedObject var store: Store var body: some View { ChildView(store: _store) }

October 24, 2020 路 1 min 路 Khoa Pham