How to use SwiftUI Charts
Issue #907 Read more https://swdevnotes.com/swift/2022/customise-a-line-chart-with-swiftui-charts-in-ios-16/ https://github.com/jordibruin/Swift-Charts-Examples
Issue #907 Read more https://swdevnotes.com/swift/2022/customise-a-line-chart-with-swiftui-charts-in-ios-16/ https://github.com/jordibruin/Swift-Charts-Examples
Issue #906 Read more https://developer.apple.com/documentation/widgetkit/making-a-configurable-widget What is the purpose of getSnapshot method from WidgetKit
Issue #905 Protect mutable state with Swift actors Actor reentrancy Imagine we have two different concurrent tasks trying to fetch the same image at the same time. The first sees that there is no cache entry, proceeds to start downloading the image from the server, and then gets suspended because the download will take a while. While the first task is downloading the image, a new image might be deployed to the server under the same URL....
Issue #904 Consider this code where we have an ObservableObject with fetch1 and async fetch2, and a fetch inside ContentView Here the observation in Xcode 14 ViewModel.fetch1: run on main thread ViewModel.fetch2: run on cooperative thread pool ContentView.fetch: run on main thread import SwiftUI import CoreData import Combine class ViewModel: ObservableObject { @Published var string = "" func fetch1() { let url = URL(string: "https://google.com")! let data = try! Data(contentsOf: url) self....
Issue #903 let image = NSImage(contentsOf: url) let imageView = NSImageView(image: image) image.animates = true
Issue #902 iOS 13 Intents Extension & Intents UI Extension Donate Shortcuts at the Right Time Siri can predict shortcuts to actions that a user may want to perform using your app, and suggest those shortcuts to the user in places such as Spotlight search, Lock Screen, and the Siri watch face. Siri learns about the shortcuts available for your app through donations that your app makes to Siri. To handle the shortcut, implement the application(_:continue:restorationHandler:) method in your app delegate....
Issue #901 Apple app site association https://com.example/.well-known/apple-app-site-association Supporting Associated Domains New format from iOS 13 Can also remove components section if we match all URLs { "applinks": { "details": [ { "appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ], "components": [ { "/": "/*", "comment": "Match all URLs" } } ] }, } Application Identifier Prefix appID is in form <Application Identifier Prefix>.<Bundle Identifier> For Application Identifier Prefix , you can find it in https://developer....
Issue #900 Listen to didActivateApplicationNotification and check that it is not our app NSWorkspace.shared.notificationCenter .publisher(for: NSWorkspace.didActivateApplicationNotification) .sink(receiveValue: { [weak self] note in guard let app = note.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication, app.bundleIdentifier != Bundle.main.bundleIdentifier else { return } self?.frontMostApp = app }) .store(in: &bag)
Issue #899 Use NSTitlebarAccessoryViewController var titleBarAccessoryVC: NSTitlebarAccessoryViewController { let vc = NSTitlebarAccessoryViewController() let view = HStack { Spacer() Button { } label: { Text("Save") } .buttonStyle(.borderedProminent) .controlSize(.large) } .padding(.horizontal) vc.view = NSHostingView(rootView: view) return vc } let window: NSWindow = ... window.addTitlebarAccessoryViewController(titleBarAccessoryVC)
Issue #898 Change element position using either offset or position, and use DragGesture Use GestureState to store the updating startDragLocation to keep the start location when drag begins, so we can add translation struct MoveModifier: ViewModifier { @Binding var position: CGPoint @GestureState private var startLocation: CGPoint? func body(content: Content) -> some View { content .gesture(gesture) } private var gesture: some Gesture { DragGesture() .onChanged { value in var position = startLocation ?...
Issue #897 During continuous events like dragging or TextField typing, and we have a Picker onscreen with large data set, it will slow down main thread. One option is to explicitly conform that view to Equatable struct FontPicker: View, Equatable { @Binding var fontFamily: String var body: some View { Picker("", selection: $fontFamily) { ForEach(NSFontManager.shared.availableFontFamilies, id: \.self) { family in Text(family) .tag(family) } } } static func == (l: FontPicker, r: FontPicker) -> Bool { l....
Issue #896 Use underscore _focus we get access to underlying FocusState object, but underscore _ is private to a View hence can’t be used in extension If we want to pass FocusState to another View or in extension, we can pass its Binding enum FocusElement: Hashable { case name case email } struct ParentView: View { @FocusState var focus: FocusElement? var body: some View { ChildView1(focus: _focus) ChildView2(focus: $focus) } } struct ChildView1: View { @FocusState var focus: FocusElement?...
Issue #895 Apply .move on reversed array List(selection: $viewModel.selectedBook) { ForEach(viewModel.books.reversed()) { book in BookCell(book: book) } .onMove { source, dest in var reversed = Array(viewModel.books.reversed()) reversed.move(fromOffsets: source, toOffset: dest) viewModel.books = reversed.reversed() } }
Issue #894 Use a UIView as source view and set it in background class ViewModel { lazy var sourceView = UIView() } struct SourceView: UIViewRepresentable { let viewModel: ViewModel func makeUIView(context: Context) -> UIView { viewModel.sourceView } func updateUIView(_ uiView: UIView, context: Context) {} } Button(action: { onShowAlert(viewModel.sourceView) }) { Image(systemName: "bookmark") } .background(SourceView(viewModel: viewModel)) let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) alertController.popoverPresentationController?.sourceView = viewModel.sourceView
Issue #892 WWDC21 Building a Great Mac App with SwiftUI Add Rich Graphics to Your SwiftUI App
Issue #891 Below are my favorite WWDC videos. My focus is to use SwiftUI to make useful apps with great UX. I don’t pay much attention to new frameworks as they come and go, but the underlying reasons and design principles are worth remembering. WWDC23 The SwiftUI cookbook for focus Discussing some of the things that you can do with focus APIs in SwiftUI to cook up a really great user experience...
Issue #890 In WWDC21, WWDC22 Apple provide a Slack channel https://wwdc22.slack.com/ for people to interact with Apple engineers in digital lounges. Here I note down some interesting Q&As WWDC22 What’s the difference between a custom ViewModifier vs View extension Q: What’s the difference between a custom ViewModifier (without DynamicProperty) that uses some built-in modifiers in body(content:), and a custom View extension func that just use those built-in modifiers? Similarly, what’s the difference between a custom ViewModifier with some DynamicProperty and a custom View with some DynamicProperty (also has a @ViewBuilder content property to receive content to modify) ?...
Issue #890 Interesting SwiftUI Q&A during WWDC22 What’s the difference between a custom ViewModifier vs View extension Q: What’s the difference between a custom ViewModifier (without DynamicProperty) that uses some built-in modifiers in body(content:), and a custom View extension func that just use those built-in modifiers? Similarly, what’s the difference between a custom ViewModifier with some DynamicProperty and a custom View with some DynamicProperty (also has a @ViewBuilder content property to receive content to modify) ?...
Issue #889 What’s new in SwiftUI New EnvironmentValues TextField inside Alert List uses UICollectionView See gist https://gist.github.com/onmyway133/fc08111964984ef544a176a6e9806c18 ButtonStyle composition Section("Hashtags") { VStack(alignment: .leading) { HStack { Toggle("#Swiftastic", isOn: $swiftastic) Toggle("#WWParty", isOn: $wwdcParty) } HStack { Toggle("#OffTheCharts", isOn: $offTheCharts) Toggle("#OneMoreThing", isOn: $oneMoreThing) } } .toggleStyle(.button) .buttonStyle(.bordered) } Customize Charts struct MonthlySalesChart: View { var body: some View { Chart(data, id: \.month) { BarMark( x: .value("Month", $0.month, unit: .month), y: .value("Sales", $0.sales) ) } ....
Issue #888 Embrace Swift generics This generic pattern is really common, so there’s a simpler way to express it. Instead of writing a type parameter explicitly, we can express this abstract type in terms of the protocol conformance by writing “some Animal”. The “some” in “some Animal” indicates that there is a specific type that you’re working with. func feed<A>(animal: A) where A: Animal {} func feed(animal: some Animal) An abstract type that represents a placeholder for a specific concrete type is called an opaque type....