How to check if NSColor is light

Issue #627 Algorithm from https://www.w3.org/WAI/ER/WD-AERT/#color-contrast extension NSColor { var isLight: Bool { guard let components = cgColor.components, components.count >= 3 else { return false } let brightness = ((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000 return brightness > 0.5 } } Then we can apply contrast color for our Text extension Text { func applyColorBaseOnBackground(_ color: NSColor?) -> some View { guard let color = color else { return self } if color....

March 20, 2020 路 1 min 路 Khoa Pham

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: NSViewRepresentableContext<AppearAware>) -> AwareView { let view = AwareView() view.onAppear = onAppear return view } func updateNSView(_ nsView: AwareView, context: NSViewRepresentableContext<AppearAware>) { } } final class AwareView: NSView { private var trigged: Bool = false var onAppear: () -> Void = {} override func viewDidMoveToSuperview() { super....

March 18, 2020 路 1 min 路 Khoa Pham

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 路 Khoa Pham

How to access bookmark url in macOS

Issue #624 By default the approaches above grant you access while the app remains open. When you quit the app, any folder access you had is lost. To gain persistent access to a folder even on subsequent launches, we鈥檒l have to take advantage of a system called Security-Scoped Bookmarks. Add entitlements Use of app-scoped bookmarks and URLs <key>com.apple.security.files.user-selected.read-only</key> <true/> <key>com.apple.security.files.bookmarks.app-scope</key> <true/> Enabling Security-Scoped Bookmark and URL Access...

March 17, 2020 路 2 min 路 Khoa Pham

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 路 Khoa Pham

How to make tooltip in SwiftUI for macOS

Issue #617 On macOS 11, we can use .help modifier to add tooltip Button() .help("Click here to open settings") If you support macOS 10.15, then create empty NSView and use as overlay. Need to updateNSView in case we toggle the state of tooltip import SwiftUI struct Tooltip: NSViewRepresentable { let tooltip: String func makeNSView(context: NSViewRepresentableContext<Tooltip>) -> NSView { let view = NSView() view.toolTip = tooltip return view } func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<Tooltip>) { nsView....

March 11, 2020 路 1 min 路 Khoa Pham

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 路 Khoa Pham

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 路 Khoa Pham

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 路 Khoa Pham

How to animate NSWindow

Issue #609 Use animator proxy and animate parameter var rect = window.frame rect.frame.origin.x = 1000 NSAnimationContext.runAnimationGroup({ context in context.timingFunction = CAMediaTimingFunction(name: .easeIn) window.animator().setFrame(rect, display: true, animate: true) }, completionHandler: { })

February 23, 2020 路 1 min 路 Khoa Pham

How to find active application in macOS

Issue #608 An NSRunningApplication instance for the current application. NSRunningApplication.current The running app instance for the app that receives key events. NSWorkspace.shared.frontmostApplication 聽

February 22, 2020 路 1 min 路 Khoa Pham

How to use application will terminate in macOS

Issue #601 On Xcode 11, applicationWillTerminate is not called because of default automatic termination on in Info.plist. Removing NSSupportsSuddenTermination to trigger will terminate notification func applicationWillTerminate(_ notification: Notification) { save() } <key>NSSupportsAutomaticTermination</key> <true/> <key>NSSupportsSuddenTermination</key> <true/>

February 12, 2020 路 1 min 路 Khoa Pham

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 } Updated at 2020-08-14 07:26:27

February 4, 2020 路 1 min 路 Khoa Pham

How to weak link Combine in macOS 10.14 and iOS 12

Issue #593 #if canImport(Combine) is not enough, need to specify in Other Linker Flags OTHER_LDFLAGS = -weak_framework Combine Read more https://stackoverflow.com/questions/57168931/optional-linking-for-swift-combine-framework-in-xcode-11

February 2, 2020 路 1 min 路 Khoa Pham

How to set font to NSTextField in macOS

Issue #591 Use NSTextView instead

January 29, 2020 路 1 min 路 Khoa Pham

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 { VStack(alignment: .leading, spacing: 0) { BorderlessTextField(placeholder: placeholder, text: $text, isFocus: $isFocus) .frame(maxHeight: 40) Rectangle() .foregroundColor(isFocus ? R.color.separatorFocus : R.color.separator) .frame(height: isFocus ? 2 : 1) } } } class FocusAwareTextField: NSTextField { var onFocusChange: (Bool) -> Void = { _ in } override func becomeFirstResponder() -> Bool { let textView = window?...

January 29, 2020 路 2 min 路 Khoa Pham

How to make focusable NSTextField in macOS

Issue #589 Use onTapGesture import SwiftUI struct MyTextField: View { @Binding var text: String let placeholder: String @State private var isFocus: Bool = false var body: some View { FocusTextField(text: $text, placeholder: placeholder, isFocus: $isFocus) .padding() .cornerRadius(4) .overlay( RoundedRectangle(cornerRadius: 4) .stroke(isFocus ? Color.accentColor: Color.separator) ) .onTapGesture { isFocus = true } } } private struct FocusTextField: NSViewRepresentable { @Binding var text: String let placeholder: String @Binding var isFocus: Bool func makeNSView(context: Context) -> NSTextField { let tf = NSTextField() tf....

January 29, 2020 路 2 min 路 Khoa Pham

How to observe focus event of NSTextField in macOS

Issue #589 becomeFirstResponder class FocusAwareTextField: NSTextField { var onFocusChange: (Bool) -> Void = { _ in } override func becomeFirstResponder() -> Bool { let textView = window?.fieldEditor(true, for: nil) as? NSTextView textView?.insertionPointColor = R.nsColor.action onFocusChange(true) return super.becomeFirstResponder() } } textField.delegate // NSTextFieldDelegate func controlTextDidEndEditing(_ obj: Notification) { onFocusChange(false) } NSTextField and NSText https://stackoverflow.com/questions/25692122/how-to-detect-when-nstextfield-has-the-focus-or-is-its-content-selected-cocoa When you clicked on search field, search field become first responder once, but NSText will be prepared sometime somewhere later, and the focus will be moved to the NSText....

January 29, 2020 路 1 min 路 Khoa Pham

How to change caret color of NSTextField in macOS

Issue #588 class FocusAwareTextField: NSTextField { var onFocus: () -> Void = {} var onUnfocus: () -> Void = {} override func becomeFirstResponder() -> Bool { onFocus() let textView = window?.fieldEditor(true, for: nil) as? NSTextView textView?.insertionPointColor = R.nsColor.action return super.becomeFirstResponder() } override func resignFirstResponder() -> Bool { onUnfocus() return super.resignFirstResponder() } }

January 29, 2020 路 1 min 路 Khoa Pham

How to make TextView in SwiftUI for macOS

Issue #587 Use NSTextVIew From https://github.com/twostraws/ControlRoom/blob/main/ControlRoom/NSViewWrappers/TextView.swift import SwiftUI /// A wrapper around NSTextView so we can get multiline text editing in SwiftUI. struct TextView: NSViewRepresentable { @Binding private var text: String private let isEditable: Bool init(text: Binding<String>, isEditable: Bool = true) { _text = text self.isEditable = isEditable } init(text: String) { self.init(text: Binding<String>.constant(text), isEditable: false) } func makeNSView(context: Context) -> NSScrollView { let text = NSTextView() text.backgroundColor = isEditable ?...

January 29, 2020 路 2 min 路 Khoa Pham