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 } List { ForEach(notes) { note in NoteRow(note: note, id: UUID()) } } Updated at 2020-11-20 03:29:39

March 17, 2020 · 1 min · 58 words · Khoa

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 ListView: View { @Environment(\.managedObjectContext) var context private var didSave = NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave) @State private var refreshing: Bool = false var body: some View { makeContent() .onReceive(didSave) { _ in self.refreshing.toggle() } } } We need to actually use that State variable for it to have effect...

March 16, 2020 · 1 min · 81 words · Khoa

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 persistence layer and those entities are also in memory, it is important that you notify the application that the objects in memory are stale and need to be refreshed. To do this, first make sure the resultType of the NSBatchDeleteRequest is set to NSBatchDeleteRequestResultType....

March 15, 2020 · 1 min · 191 words · Khoa

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: .leading) { SearchView( onSearch: self.onSearch ) InsideListView(fetchRequest: makeFetchRequest()) } } private func makeFetchRequest() -> FetchRequest<Book> { let predicate: NSPredicate? if let search = search { let textPredicate = NSPredicate(format: "string CONTAINS[cd] %@", search.text) let appPredicate = NSPredicate(format: "appName == %@", search.app) let typePredicate = NSPredicate(format: "type == %@", search....

March 14, 2020 · 1 min · 190 words · Khoa

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 { true } } Furthermore to customize TextField, consider using custom import SwiftUI import AppKit struct MyTextField: NSViewRepresentable { @Binding var text: String func makeNSView(context: NSViewRepresentableContext<MyTextField>) -> NSTextField { let tf = NSTextField() tf.focusRingType = ....

March 13, 2020 · 1 min · 135 words · Khoa

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) } } } func makeIsPresented(item: Item) -> Binding<Bool> { return .init(get: { return self.selectedId == item.id }, set: { _ in self.selectedId = nil }) }

March 11, 2020 · 1 min · 46 words · Khoa

How to make translucent SwiftUI List in macOS

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

March 5, 2020 · 1 min · 14 words · Khoa

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: "one", text: "One", tab: .one) OneTabView(image: "two", text: "Two", tab: .two) OneTabView(image: "three", text: "Three", tab: .three) Spacer() } } } struct OneTabView: View { @EnvironmentObject var preferenceManager: PreferenceManager let image: String let text: String let tab: Tab var selected: Bool { preferenceManager.preference.tab == tab } var body: some View { Button(action: { self....

March 2, 2020 · 1 min · 117 words · Khoa

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 self.content = content } var body: some View { makeContent() } private func makeContent() -> some View { if isVertical { return VStack(spacing: 0) { content() }.eraseToAnyView() } else { return HStack(spacing: 0) { content() }.eraseToAnyView() } } }

March 2, 2020 · 1 min · 68 words · Khoa

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 yourself.) While the app is in that loop, it does not respond to any other events (including mouse, keyboard, or window-close events) unless they are associated with the window....

March 2, 2020 · 1 min · 190 words · Khoa

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(\.managedObjectContext, coreDataManager.container.viewContext) window = NSWindow( contentRect: .zero, styleMask: [.fullSizeContentView], backing: .buffered, defer: false ) window.titlebarAppearsTransparent = true window.center() window.level = .statusBar window.setFrameAutosaveName("MyApp") let visualEffect = NSVisualEffectView() visualEffect.blendingMode = .behindWindow visualEffect.state = ....

February 27, 2020 · 1 min · 87 words · Khoa

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(context: Context) -> NSTextView { let textView = NSTextView() textView.delegate = context.coordinator return textView } func updateNSView(_ nsView: NSTextView, context: Context) { guard nsView.string != text else { return } nsView.string = text } class Coordinator: NSObject, NSTextViewDelegate { let parent: TextView init(_ textView: TextView) { self....

February 14, 2020 · 2 min · 282 words · Khoa

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 { let text: String func body(content: Content) -> some View { print(text) return content .onAppear {} } } extension View { func log(_ text: String) -> some View { self.modifier(LogModifier(text: text)) } } VStack { Text("") ....

February 14, 2020 · 1 min · 102 words · Khoa

How to avoid pitfalls in SwiftUI

Issue #602 Identify by unique id ForEach(store.blogs.enumerated().map({ $0 }), id: \.element.id) { index, blog in } ``` ##

February 12, 2020 · 1 min · 18 words · Khoa

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(Authentication.key) CertificateAuthenticationView() .tabItem { Text("📰 Certificate") } .tag(Authentication.certificate) }

February 11, 2020 · 1 min · 32 words · Khoa

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 if we abstract over it, then it becomes super hard to customize. Every app is unique, and any attempt to wrap around UICollectionView will fail horribly. A sensable approach for a good abstraction is to make it super easy for normal cases, and easy to customize for advanced scenarios....

February 9, 2020 · 4 min · 832 words · Khoa

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.inputBorderFocus : Color.clear, lineWidth: 1) )

February 5, 2020 · 1 min · 24 words · Khoa

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 }

February 4, 2020 · 1 min · 28 words · Khoa

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, .text ] } func handleDrop(info: DropInfo) -> Bool { for provider in info.itemProviders(for: dropTypes) { for type in dropTypes { provider.loadDataRepresentation(forTypeIdentifier: type.identifier) { data, _ in guard let data = data, let string = String(data: data, encoding: .utf8) else { return } DispatchQueue....

February 4, 2020 · 2 min · 218 words · Khoa

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 custom view Use contentShape to make whole button tappable. Make custom Binding for our enum struct EnvironmentView: View { @Binding var input: Input var body: some View { VStack(alignment: .leading) { RadioButton(text: "Production", isOn: binding(for: .production)) RadioButton(text: "Sandbox", isOn: binding(for: .sandbox)) } } private func binding(for environment: Input.Environment) -> Binding<Bool> { Binding<Bool>( get: { self....

February 1, 2020 · 1 min · 157 words · Khoa