How to handle NSSearchToolbarItem in macOS 11

Issue #758 extension NSToolbarItem.Identifier { static let searchItem: NSToolbarItem.Identifier = NSToolbarItem.Identifier("SearchItem") } let searchItem = NSSearchToolbarItem(itemIdentifier: .searchItem) extension AppDelegate: NSToolbarDelegate { func toolbar( _ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool ) -> NSToolbarItem? { switch itemIdentifier { case .searchItem: searchItem.searchField.delegate = self return searchItem } } extension AppDelegate: NSSearchFieldDelegate { func control( _ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector ) -> Bool { if (commandSelector == #selector(NSResponder.insertNewline(_:))) { print("enter") return true } return false } }

January 21, 2021 路 1 min 路 Khoa Pham

How to do launch at login for macOS apps

Issue #757 Use SMLoginItemSetEnabled from Service Management framework Use a helper background app that checks and invokes our main application Copy our helper app into Library/LoginItems helper_dir="$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems" final class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { let bundleId = Bundle.main.bundleIdentifier! // TODO:Make this more strict by only replacing at the end let mainBundleId = bundleId.replacingOccurrences(of: "-LaunchAtLoginHelper", with: "") // Ensure the app is not already running guard NSRunningApplication....

January 20, 2021 路 1 min 路 Khoa Pham

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() } } } Read more https://www.dabblingbadger.com/blog/2020/12/11/a-quick-fix-for-overlapping-navigation-titles-in-swiftui As far as I can tell, this bug only shows up if you: 1) have the navigation title displayMode of a destination view set to .large and 2) have added items to the navigation bar using the .navigationBarItems modifier....

January 20, 2021 路 1 min 路 Khoa Pham

How to use NSWindow style and NSToolbar in AppKit

Issue #755 Read more https://github.com/martinlexow/SwiftUIWindowStyles https://github.com/lukakerr/NSWindowStyles https://github.com/marioaguzman/toolbar

January 20, 2021 路 1 min 路 Khoa Pham

How to use NSSplitViewController in AppKit

Issue #754 Read more https://github.com/KevinGutowski/SplitConfigurations

January 20, 2021 路 1 min 路 Khoa Pham

How to add alternative app icons for iOS

Issue #749 Some apps want to support alternative app icons in Settings where user can choose to update app icon. Here鈥檚 some must do to make it work, as of Xcode 12.2 In Info.plist, must declare CFBundleIcons with both CFBundlePrimaryIcon and CFBundleAlternateIcons Icons must be in project folder, not Asset Catalog Here鈥檚 how it is done on my app PastePal Add app icons to project folder Prepare icons, like Icon1, Icon2 with 2 variants for 2x and 3x....

January 14, 2021 路 2 min 路 Khoa Pham

How to make popup button in SwiftUI for macOS

Issue #748 There is said to be PopUpButtonPickerStyle and MenuPickerStyle but these don鈥檛 seem to work. There鈥檚 Menu button it shows a dropdown style. We fake it by fading this and overlay with a button. allowsHitTesting does not work, but disabled seems to do the trick Menu { Button("About", action: ActionService.onAbout) Button("Quit", action: ActionService.onQuit) } label: { Text("") } .frame(width: 24) .opacity(0.01) .overlay( makeButton(action: {}, "gearshape.fill") .disabled(true) .foregroundColor(Color.secondaryLabel) ) Follow pika...

January 13, 2021 路 1 min 路 Khoa Pham

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, UITextViewDelegate { let parent: MyTextView init(parent: MyTextView) { self.parent = parent } func textViewDidChange(_ textView: UITextView) { if textView.text != parent.text { parent.text = textView.text } } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIView(context: Context) -> UITextView { let view = UITextView() view....

January 8, 2021 路 1 min 路 Khoa Pham

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> <dict> <key>UIApplicationSupportsMultipleScenes</key> <true/> </dict> One way to be notified about application life cycle is to use UIApplicationDelegateAdaptor and via NotificationCenter import SwiftUI import UIKit import FontAwesomeSwiftUI final class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { FontAwesome....

January 7, 2021 路 1 min 路 Khoa Pham

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") .tag(Tag.all) } From the API, looks like Binding<Set> is for multiple selection, and Binding<Optional> is for single selection Looking at List signature, I see that selection uses wrappedValue as Set for Binding<Set<SelectionValue>>? init<Data, ID, RowContent>(Data, id: KeyPath<Data....

January 6, 2021 路 1 min 路 Khoa Pham

How to simplify communication patterns with closure in Swift

Issue #744 As someone who builds lots of apps, I try to find quick ways to do things. One of them is to avoid repetitive and cumbersome APIs. That鈥檚 why I built Anchors to make Auto Layout more convenient, Omnia to add missing extensions. The next thing in the itchy list is the many ways to communicate among objects in iOS and macOS development that can be very annoying sometimes....

January 6, 2021 路 11 min 路 Khoa Pham

How to make Auto Layout more convenient in iOS

Issue #742 Auto Layout has been around since macOS 10.7 and iOS 6.0 as a nicer way to do layouts over the old resizing masks. Besides some rare cases when we need to manually specify origins and sizes, Auto Layout is the preferred way to do declarative layouts whether we choose to do UI in code or Storyboard. The Auto Layout APIs have some improvements over the years, there are also some sugar libraries that add easy syntaxes, so more choices for developers....

January 5, 2021 路 18 min 路 Khoa Pham

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) .frame(maxWidth: .infinity, maxHeight: .infinity) .clipped()

January 2, 2021 路 1 min 路 Khoa Pham

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 { let view = WKWebView() view.navigationDelegate = context.coordinator view.load(URLRequest(url: url)) return view } func updateNSView(_ nsView: WKWebView, context: Context) { } class Coordinator: NSObject, WKNavigationDelegate { let parent: MyWebView init(parent: MyWebView) { self.parent = parent } func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { parent....

January 2, 2021 路 1 min 路 Khoa Pham

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 whole width and height of parent, and align its content as .topLeading struct ContentView_Previews: PreviewProvider { static var previews: some View { VStack { Rectangle() .fill(Color.gray) .overlay( GeometryReader { geo in Text("\(Int(geo....

January 1, 2021 路 1 min 路 Khoa Pham

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 disable scrolling in NSTextView for macOS

Issue #733 NSTextView has this handy method to make scrollable NSTextView NSTextView.scrollableTextView(). The solution is to get to the responder outside enclosing NSScrollView, in my case it is the SwiftUI hosting view class DisabledScrollTextView: NSTextView { override func scrollWheel(with event: NSEvent) { // 1st nextResponder is NSClipView // 2nd nextResponder is NSScrollView // 3rd nextResponder is NSResponder SwiftUIPlatformViewHost self.nextResponder?.nextResponder?.nextResponder?.scrollWheel(with: event) } } Then we can construct with our new DisabledScrollTextView.scrollableTextView

December 31, 2020 路 1 min 路 Khoa Pham

How to override attribute string in Swift

Issue #732 Use NSMutableAttributedString and add attribute for whole range let a: NSAttributedString let m: NSMutableAttributedString = NSMutableAttributedString(attributedString: a) let range = NSRange(location: 0, length: a.length) m.addAttribute(.backgroundColor, value: NSColor.clear, range: range)

December 31, 2020 路 1 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