How to name Boolean property in Swift

Issue #787 In Swift, property, especially for Boolean flagging, uses the regular verb form for the third person. There are few exceptions, such as enable NSManagedObjectContext.automaticallyMergesChangesFromParent UIView.clipsToBounds UIView.translatesAutoresizingMaskIntoConstraints SwiftUI.Transaction.disablesAnimations UIScrollView.scrollsToTop NSView.isHidden UndoManager.enableUndoRegistration Updated at 2021-02-28 22:34:53...

February 28, 2021 路 1 min 路 Khoa Pham

How to use with block configure in Swift

Issue #786 Sometimes we need to update some properties between objects, for example book.name = updatedBook.name book.page = updatedBook.page book.publishedAt = updatedBook.publishedAt Repeating the caller book is tedious and error-prone. In Kotlin, there is with block which is handy to access the receiver properties and methods without referring to it. with(book) { name = updatedBook.name page = updatedBook.page publishedAt = updatedBook.publishedAt } In Swift, there are no such thing, we can write some extension like...

February 28, 2021 路 1 min 路 Khoa Pham

How to use Core Data

Issue #785 Some links to learn Core Data Responding to changes in a managed object context 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 information. Note that you don鈥檛 have to call mergeChanges on a viewContext when you set its automaticallyMergesChangesFromParent property to true. In that case, Core Data will handle the merge on your behalf....

February 26, 2021 路 5 min 路 Khoa Pham

How to listen to remote changes in CloudKit CoreData

Issue #783 Remove chane notification Read Consuming Relevant Store Changes If the import happens through a batch operation, the save to the store doesn鈥檛 generate an NSManagedObjectContextDidSave notification, and the view misses these relevant updates. Alternatively, the background context may save changes to the store that don鈥檛 affect the current view鈥攆or example, inserting, modifying, or deleting Shape objects. These changes do generate context save events, so your view context processes them even though it doesn鈥檛 need to....

February 25, 2021 路 1 min 路 Khoa Pham

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, scheduler: RunLoop.main, latest: true) .receive(on: RunLoop.main) .sink(receiveValue: { shows in preferenceManager.reloadPosition(shows: shows) }) .store(in: &anyCancellables) Updated at 2021-02-25 21:56:42...

February 25, 2021 路 1 min 路 Khoa Pham

How to filter non numeric digit from String in Swift

Issue #781 This sounds like an easy task, but a quick search on Stackoverflow results in this with highest votes https://stackoverflow.com/questions/29971505/filter-non-digits-from-string CharacterSet.decimalDigits contains more than just digits This splits a string by inverted set of decimalDigits and join them back. extension String { var digits: String { return components(separatedBy: CharacterSet.decimalDigits.inverted) .joined() } } Reading decimalDigits Informally, this set is the set of all characters used to represent the decimal values 0 through 9....

February 25, 2021 路 2 min 路 Khoa Pham

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() } var body: some View { content } } From Swift 5.4, it can synthesize the init, so we can declare resultBuilder for stored property struct AwesomeContainerView<Content: View>: View { @ViewBuilder let content: Content var body: some View { content } } Updated at 2021-02-24 21:22:49...

February 24, 2021 路 1 min 路 Khoa Pham

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鈥檚 an increasing number of ButtonBehavior Suspect State in a row in LazyVStack Every cell has its own toggle state struct Cell: View { enum ToggleState { case general case request case response } let item: Item @State private var toggleState: ToggleState = ....

February 24, 2021 路 1 min 路 Khoa Pham

How to use GroupBox in SwiftUI

Issue #778 For now using GroupBox has these issues in macOS Prevents dragging scroll indicator to scroll Switch from light to dark mode may cause 100% CPU usage Updated at 2021-02-23 22:02:25...

February 23, 2021 路 1 min 路 Khoa Pham

How to suppress selector warning in Swift

Issue #777 Sometimes we need to use dynamic selector and that triggers warning in Swift Selector("updateWithCount:") // Use '#selector' instead of explicitly constructing a 'Selector' In ObjC we can use clang macro to suppress, like below #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void) deprecated_objc_method_override { } #pragma clang diagnostic pop But in Swift, we can just use a dummy NSObject that has the needed methods, like...

February 18, 2021 路 1 min 路 Khoa Pham

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 EasySwiftUI struct SearchBar: View { @Binding var searchText: String let onChange: () -> Void @State private var showsCancelButton: Bool = false var body: some View { return HStack { textField cancelButton } } private var searchTextBinding: Binding<String> { Binding<String>(get: { searchText }, set: { newValue in DispatchQueue....

February 17, 2021 路 1 min 路 Khoa Pham

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 var shortcutItem: UIApplicationShortcutItem { switch self { case .readPasteboard: return UIApplicationShortcutItem( type: rawValue, localizedTitle: "Read Pasteboard", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .add), userInfo: nil ) case .clear: return UIApplicationShortcutItem( type: rawValue, localizedTitle: "Clear Pasteboard", localizedSubtitle: "", icon: UIApplicationShortcutIcon(systemImageName: SFSymbol.wind.rawValue), userInfo: nil ) } } } Add a service to store selected quick action....

February 10, 2021 路 2 min 路 Khoa Pham

How to use EquatableView in SwiftUI

Issue #773 From John Harper 鈥檚 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鈥檚 == but falls back to its own field compare if no ==. EqView is a way to force the use of ==. When it does the per-field comparison the same rules are applied recursively to each field (to choose direct comparison or == if defined)....

February 8, 2021 路 1 min 路 Khoa Pham

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鈥檛 decode with old saved json as we require new properties. We can either do cutom decoding with container, but this can result in lots more code and mistakes if we have many properties inside our struct. The quick workaround is to declare new properties as optional, and use a computed property to wrap that....

February 8, 2021 路 1 min 路 Khoa Pham

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

February 6, 2021 路 1 min 路 Khoa Pham

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 the local frame import SwiftUI struct HSearchBar: View { @State private var scrollViewContentSize: CGSize = .zero var body: some View { HStack { searchButton ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 12) { ForEach(store....

February 6, 2021 路 1 min 路 Khoa Pham

How to show modal window in SwiftUI for macOS

Issue #768 Use custom NSWindow, set level in becomeKey and call NSApp.runModal to show modal final class ModalWindow: NSWindow { override func becomeKey() { super.becomeKey() level = .statusBar } override func close() { super.close() NSApp.stopModal() } } let window = ModalWindow( contentRect: .zero, styleMask: [.titled, .closable], backing: .buffered, defer: false ) window.titlebarAppearsTransparent = true window.title = "Manage collections" window.center() window.isReleasedWhenClosed = false self.window = window let view = CollectionSettingsView(store: Store.shared) ....

February 3, 2021 路 1 min 路 Khoa Pham

How to use ViewBuilder in SwiftUI

Issue #767 SwiftUI 鈥檚 ViewBuilder is a custom parameter attribute that constructs views from closures. It is available in body and most SwiftUI modifiers public protocol View { associatedtype Body : View @ViewBuilder var body: Self.Body { get } } public func contextMenu<MenuItems>(@ViewBuilder menuItems: () -> MenuItems) -> some View where MenuItems : View In these ViewBuilder enabled places we can perform conditional logic to construct views. For example here in our SampleView, we have switch statement in body...

February 2, 2021 路 3 min 路 Khoa Pham

How to use custom Key for NSCache

Issue #766 Need to use a class, best is to subclass from NSObject let cache = NSCache<Key, UIImage>() final class Key: NSObject { override func isEqual(_ object: Any?) -> Bool { guard let other = object as? Key else { return false } return url == other.url && size == other.size } override var hash: Int { return url.hashValue ^ Int(size.width) ^ Int(size.height) } let url: URL let size: CGSize init(url: URL, size: CGSize) { self....

January 30, 2021 路 1 min 路 Khoa Pham

How to show multiple popover in SwiftUI

Issue #765 In SwiftUI currently, it鈥檚 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 } @Binding var showsPopover: Bool @Binding var popoverStyle: PopoverStyle var body: some View { VStack { header content .popover(isPresented: $showsPopover) { switch popoverStyle { case .raw: ViewRawView(item: item) case .preview: PreviewView(item: item) } } footer } } } ...

January 29, 2021 路 1 min 路 Khoa Pham