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 · 3711 words · Khoa

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 · 25 words · Khoa

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 · 88 words · Khoa

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 · 192 words · Khoa

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

January 1, 2021 · 7 min · 1320 words · Khoa

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 · 70 words · Khoa

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 · 31 words · Khoa

How to make view appear with delay in SwiftUI

Issue #731 Sometimes we don’t 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 · 20 words · Khoa

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 · 154 words · Khoa

How to do copy paste delete in Swift for macOS

Issue #729 @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { @IBAction func copy(_ sender: Any) { print("copy", sender) } @IBAction func paste(_ sender: Any) { print("paste", sender) } } For delete, we can listen to keyDown in NSWindow class MyWindow: NSWindow { override func keyDown(with event: NSEvent) { super.keyDown(with: event) guard let deleteScalar = UnicodeScalar(NSDeleteCharacter), event.charactersIgnoringModifiers == String(deleteScalar) else { return } NotificationCenter.default.post(Notification(name: .didKeyboardDeleteItem)) } }

December 30, 2020 · 1 min · 64 words · Khoa

How to make simple NSItemProvider in Swift

Issue #728 NSItemProvider(object: StringProvider(string: string)) class StringProvider: NSObject, NSItemProviderWriting { let string: String init(string: String) { self.string = string super.init() } static var writableTypeIdentifiersForItemProvider: [String] { return [(kUTTypeData) as String] } func loadData( withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void ) -> Progress? { let data = string.data(using: .utf8) completionHandler(data, nil) return Progress(totalUnitCount: 100) } }

December 30, 2020 · 1 min · 59 words · Khoa

How to use hashtag raw string in Swift

Issue #727 Use # in Swift 5 to specify raw string, for example regular expression #"^#?(?:[0-9a-fA-F]{3}){1,2}$"# Read more https://www.hackingwithswift.com/articles/162/how-to-use-raw-strings-in-swift

December 27, 2020 · 1 min · 19 words · Khoa

How to make UserDefaults property wrapper

Issue #726 @propertyWrapper struct UserDefault<Value> { let key: String let defaultValue: Value let container: UserDefaults = .standard var wrappedValue: Value { get { return container.object(forKey: key) as? Value ?? defaultValue } set { container.set(newValue, forKey: key) } } } Then we can use it as property and provide default value final class KeepHistoryService { @UserDefault(key: "keepHistoryCheckDate", defaultValue: nil) var checkDate: Date?

December 26, 2020 · 1 min · 61 words · Khoa

How to use Set to check for bool in Swift

Issue #725 When you want to check for existence using Bool, consider using Set over Dictionary with Bool, as Set guarantee uniqueness. If using Dictionary instead, the value for key is Optional<Bool> where we have to check for both optional and true false within. struct Book: Hashable { let id: UUID let name: String } let book1 = Book(id: UUID(), name: "1") let book2 = Book(id: UUID(), name: "2") func useDictionary() { var hasChecked: [Book: Bool] = [:] hasChecked[book1] = true print(hasChecked[book1] == Optional<Bool>(true)) print(hasChecked[book2] == Optional<Bool>....

December 26, 2020 · 1 min · 100 words · Khoa

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 · 88 words · Khoa

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 · 132 words · Khoa

How to force set frame explicitly for NSWindow

Issue #721 For setFrame to take effect mainWindow.setFrame(rect, display: true) we can remove auto save frame flag mainWindow.setFrameAutosaveName("MyApp.MainWindow")

December 25, 2020 · 1 min · 18 words · Khoa

How to rotate NSStatusItem

Issue #720 NSStatusItem is backed by NSButton, we can animate this inner button. We need to specify position and anchorPoint for button’s layer so it rotates around its center point guard let button = statusItem.button else { return } let animation = CABasicAnimation(keyPath: "transform.rotation.z") animation.fromValue = 0 animation.toValue = CGFloat.pi * 2 animation.duration = 0.25 animation.repeatCount = 1 button.layer?.position = NSPoint(x: NSMidX(button.frame), y: NSMidY(button.frame)) button.layer?.anchorPoint = NSPoint(x: 0.5, y: 0.5) button....

December 23, 2020 · 1 min · 73 words · Khoa

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 · 112 words · Khoa

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 · 325 words · Khoa