How to set text color for UIDatePicker
Issue #660
Apply tintColor
does not seem to have effect.
1 | datePicker.setValue(UIColor.label, forKeyPath: "textColor") |
Updated at 2020-06-10 19:15:21
Issue #660
Apply tintColor
does not seem to have effect.
1 | datePicker.setValue(UIColor.label, forKeyPath: "textColor") |
Updated at 2020-06-10 19:15:21
Issue #656
Lately I’ve been challenging myself to declare switch statement in SwiftUI, or in a more generalized way, execute any anonymous function that can return a View
Note that this approach does not work yet, as TupeView
should support variadic number of contents, and also T.RawValue needs to conform to Equatable in order to check the cases.
Also in Switch statement, Content can’t be inferred
1 | struct Case<T: RawRepresentable, Content: View>: View { |
Another solution is to use a MakeView
view, this is more generic as it can execute any functions
1 | enum Animal: String { |
Updated at 2020-05-22 20:42:14
Issue #646
Pass DispatchQueue
and call queue.sync
to sync all async works before asserting
Use DispatchQueueType
and in mock, call the work immediately
1 | import Foundation |
Issue #644
1 | import XCTest |
Updated at 2020-04-28 09:23:59
Issue #639
Never use String(format: "%.2f %%", 1.2
because each region can have different separator and placement of percent sign.
Use NumberFormatter
instead
1 | let formatter = NumberFormatter() |
1 | formatter.locale = Locale(identifier: "en_US") |
Note that the space created by NumberFormatter
is a non breakable space \u{00a0}
, which can be created by Alt Space
. This non breakable space is useful in UILabel
when you want the whole word to stick together
Issue #638
Use commandDefinitions
in XCSourceEditorExtension
.
1 | import Foundation |
There is a weird crash that we can’t seem to declare functions or use commandDefinitions
, the workaround is to declare in plist
Issue #638
Use commandDefinitions
in XCSourceEditorExtension
.
1 | import Foundation |
There is a weird crash that we can’t seem to declare functions or use commandDefinitions
, the workaround is to declare in plist
Issue #636
Normally we can just wrap NSTextField
1 | struct SearchTextField: NSViewRepresentable { |
But there is a weird Appstore rejection where the textfield is not focusable. The workaround is to use TextField
1 | extension NSTextField { |
Issue #635
1 | textField.delegate = self |
1 | NSTextFieldDelegate |
Issue #634
1 | public enum Weapon: String, Decodable { |
Issue #633
Use autoclosure
and AnyView
1 | 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) (iOS |
1 | Button(action: onSearch) { |
Issue #632
Use Group
1 | private func makeHeader() -> some View { |
Issue #630
For SwiftUI app using NSPopover
, to show context popover menu, we can ask for windows
array, get the _NSPopoverWindow
and calculate the position. Note that origin of macOS screen is bottom left
1 | (lldb) po NSApp.windows |
1 | let handler = MenuHandler() |
Issue #629
Use Picker
with SegmentedPickerStyle
.
1 | Picker(selection: $preferenceManager.preference.display, label: EmptyView()) { |
Alternatively, we can make custom NSSegmentedControl
1 | import AppKit |
Issue #628
1 | extension XCUIElementQuery: Sequence { |
Issue #627
Algorithm from https://www.w3.org/WAI/ER/WD-AERT/#color-contrast
1 | extension NSColor { |
Then we can apply contrast color for our Text
1 | extension Text { |
Issue #626
SwiftUI does not trigger onAppear and onDisappear like we expect. We can use NSView to trigger
1 | import SwiftUI |
Then we can use it as an hidden view, like in a ZStack
1 | ZStack { |
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
1 | struct NoteRow: View { |
Updated at 2020-11-20 03:29:39
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’ll have to take advantage of a system called Security-Scoped Bookmarks.
Add entitlements
Use of app-scoped bookmarks and URLs
1 | <key>com.apple.security.files.user-selected.read-only</key> |
Enabling Security-Scoped Bookmark and URL Access
If you want to provide your sandboxed app with persistent access to file system resources, you must enable security-scoped bookmark and URL access. Security-scoped bookmarks are available starting in macOS v10.7.3.
To add the bookmarks.app-scope or bookmarks.document-scope entitlement, edit the target’s .entitlements property list file using the Xcode property list editor. Use the entitlement keys shown in Table 4-4, depending on which type of access you want. Use a value of
for each entitlement you want to enable. You can enable either or both entitlements.
1 | func saveBookmark(item: ShortcutItem) { |
1 | _ = url.startAccessingSecurityScopedResource() |
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.resultTypeObjectIDs before the request is executed. When the request has completed successfully, the resulting NSPersistentStoreResult instance that is returned will have an array of NSManagedObjectID instances referenced in the result property. That array of NSManagedObjectID instances can then be used to update one or more NSManagedObjectContext instances.
1 | let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Book.fetchRequest() |
Issue #620
For NSWindow
having level
other than .normal
, need to override key and main property to allow TextField to be focusable
1 | class FocusWindow: NSWindow { |
Furthermore to customize TextField, consider using custom
1 | import SwiftUI |
Issue #618
Create custom Binding
1 | List { |
Issue #617
On macOS 11, we can use .help
modifier to add tooltip
1 | Button() |
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
1 | import SwiftUI |
1 | Button(action: self.onGear) { |
Now we can add tooltip as a background. Before I used to add as overlay but that prevents interaction, even with .disabled(true)
1 | Button(action: self.onGear) { |
And we can even make an extension on View
to use tooltip easily
1 | import SwiftUI |
Updated at 2020-12-12 19:54:53
Issue #614
1 | struct MyTabView: View { |
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. It also does not perform any tasks (such as firing timers) that are not associated with the modal run loop. In other words, this method consumes only enough CPU time to process events and dispatch them to the action methods associated with the modal window.
Specify level
in windowDidBecomeKey
1 | let controller = SettingsWindowController() |
Issue #611
1 | enum WindowPosition: String, CaseIterable { |
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
1 | let mainView = MainView() |
Updated at 2021-01-05 21:13:39
Issue #609
Use animator
proxy and animate
parameter
1 | var rect = window.frame |
Updated at 2020-11-22 18:26:33
Issue #608
An NSRunningApplication instance for the current application.
1 | NSRunningApplication.current |
The running app instance for the app that receives key events.
1 | NSWorkspace.shared.frontmostApplication |
Issue #607
Implement Equatable
and Comparable
and use round
1 | struct RGBA: Equatable, Comparable { |