onmyway133

Hi there, I’m Khoa aka onmyway133 👋

  • 🧑‍💻 I love crafting high quality and useful apps

  • 🔥 I love open source. My GitHub open source has 1.6k followers with packages that are integrated by 45k+ apps and over 3.4m+ downloads on CocoaPods.

  • ✍️ I write here on my blog and on Medium, which has over 2.4k+ followers with tons of articles and 90k+ monthly views.

  • 🖥 Follow me for sharings about Swift, SwiftUI, iOS and macOS development

How to repeat array of object in Swift

Issue #793 To create array containing number of repeated value in Swift, we can use Array.init(repeating:count:) let fiveZs = Array(repeating: "Z", count: 5) print(fiveZs) // Prints "["Z", "Z", "Z", "Z", "Z"]" However, if we read Collection Types guide about Creating an Array with a Default Value Swift’s Array type also provides an initializer for creating an array of a certain size with all of its values set to the same default value....

March 22, 2021 · 2 min · Khoa Pham

How to use dynamic color in iOS

Issue #792 iOS 13 introduced Dark Mode with User Interface Style that makes it easy to support dark and light theme in our apps. Before we dive in, here are some official resources WWDC 2019 Implementing Dark Mode on iOS Supporting Dark Mode in Your Interface Choosing a Specific Interface Style for Your iOS App Adaptive color Like adaptive layout that adapts to different screen sizes, adaptive colors adapt to different user interface styles, for now they are light and dark mode....

March 13, 2021 · 7 min · Khoa Pham

How to use View protocol in SwiftUI

Issue #791 SwiftUI has View protocol which represents part of your app’s user interface and provides modifiers that you use to configure views. You create custom views by declaring types that conform to the View protocol. Implement the required body computed property to provide the content for your custom view. A typical example of View is using struct enum HeroType { case melee case range } struct ContentView: View { let heroType: HeroType var body: some View { switch heroType { case ....

March 10, 2021 · 1 min · Khoa Pham

How too save image to Photo library in iOS

Issue #790 Use UIImageWriteToSavedPhotosAlbum Adds the specified image to the user’s Camera Roll album. Let’s make an NSObject delegate class so we can perform target action to notify about completion import UIKit struct ImageService { final class Delegate: NSObject { let completion: (Error?) -> Void init(completion: @escaping (Error?) -> Void) { self.completion = completion } @objc func savedImage( _ im: UIImage, error: Error?, context: UnsafeMutableRawPointer? ) { DispatchQueue.main.async { self....

March 10, 2021 · 1 min · Khoa Pham

How to manage WindowGroup in SwiftUI for macOS

Issue #789 Using WindowGroup New in SwiftUI 2.0 for iOS 14 and macOS 11.0 is WindwGroup which is used in App protocol. WindowGroup is ideal for document based applications where you can open multiple windows for different content or files. For example if you’re developing a text editor or drawing apps, you can show multiple windows for different text file or drawing. All is handled automatically for you if you use WindowGroup...

March 7, 2021 · 6 min · Khoa Pham

How to show img tag from GitHub markdown in Hugo

Issue #788 I just convert my blog https://onmyway133.com/ from Hexo.js back to Hugo again. Hugo now uses goldmark as the default markdown processor instead of blackfriday All works well, except that I use GitHub markdown to write articles, which use raw HTML img tag for uploaded images. Hugo works well with ![]() syntax but it ignores img tag <img width="574" alt="Screenshot 2021-02-26 at 10 08 38" src="https://user-images.githubusercontent.com/2284279/109279894-99d09a80-781a-11eb-9d50-10f46ba94105.png"> The solution is to tell goldmark to accept raw HTML....

March 2, 2021 · 1 min · Khoa Pham

How to name Boolean property in Swift

Issue #787 In Swift, property, especially for Boolean flagging, uses the regular verb form for the third person. There are few exceptions, such as enable NSManagedObjectContext.automaticallyMergesChangesFromParent UIView.clipsToBounds UIView.translatesAutoresizingMaskIntoConstraints SwiftUI.Transaction.disablesAnimations UIScrollView.scrollsToTop NSView.isHidden UndoManager.enableUndoRegistration ...

February 28, 2021 · 1 min · Khoa Pham

How to use with block configure in Swift

Issue #786 Sometimes we need to update some properties between objects, for example book.name = updatedBook.name book.page = updatedBook.page book.publishedAt = updatedBook.publishedAt Repeating the caller book is tedious and error-prone. In Kotlin, there is with block which is handy to access the receiver properties and methods without referring to it. with(book) { name = updatedBook.name page = updatedBook.page publishedAt = updatedBook.publishedAt } In Swift, there are no such thing, we can write some extension like...

February 28, 2021 · 1 min · Khoa Pham

How to use Core Data

Issue #785 Core Data Responding to changes in a managed object context Calling mergeChanges on a managed object context will automatically refresh any managed objects that have changed. This ensures that your context always contains all the latest information. Note that you don’t have to call mergeChanges on a viewContext when you set its automaticallyMergesChangesFromParent property to true. In that case, Core Data will handle the merge on your behalf....

February 26, 2021 · 5 min · Khoa Pham

How to force resolve Swift Package in Xcode

Issue #784 Every time I switch git branches, SPM packages seem to be invalidated and Xcode does not fetch again, no matter how many times I reopen. Running xcodebuild -resolvePackageDependencies does fetch but Xcode does not recognize the resolved packages and still reports missing packages. The good thing is under menu File -> Swift Packages there are options to reset and resolve packages...

February 26, 2021 · 1 min · Khoa Pham

How to listen to remote changes in CloudKit CoreData

Issue #783 Remove chane notification Read Consuming Relevant Store Changes If the import happens through a batch operation, the save to the store doesn’t generate an NSManagedObjectContextDidSave notification, and the view misses these relevant updates. Alternatively, the background context may save changes to the store that don’t affect the current view—for example, inserting, modifying, or deleting Shape objects. These changes do generate context save events, so your view context processes them even though it doesn’t need to....

February 25, 2021 · 1 min · Khoa Pham

How to listen to Published outside of SwiftUI view

Issue #782 Use $ to access Publisher final class Store: ObservableObject { @Published var showsSideWindow: Bool = false } var anyCancellables = Set<AnyCancellable>() store.$showsSideWindow .removeDuplicates() .throttle(for: 0.2, scheduler: RunLoop.main, latest: true) .receive(on: RunLoop.main) .sink(receiveValue: { shows in preferenceManager.reloadPosition(shows: shows) }) .store(in: &anyCancellables) ...

February 25, 2021 · 1 min · Khoa Pham

How to filter non numeric digit from String in Swift

Issue #781 This sounds like an easy task, but a quick search on Stackoverflow results in this with highest votes https://stackoverflow.com/questions/29971505/filter-non-digits-from-string CharacterSet.decimalDigits contains more than just digits This splits a string by inverted set of decimalDigits and join them back. extension String { var digits: String { return components(separatedBy: CharacterSet.decimalDigits.inverted) .joined() } } Reading decimalDigits Informally, this set is the set of all characters used to represent the decimal values 0 through 9....

February 25, 2021 · 2 min · Khoa Pham

How to build container view in SwiftUI

Issue #780 To make a container view that accepts child content, we use ViewBuilder struct ContainerView<Content: View>: View { let content: Content init(@ViewBuilder content: () -> Content) { self.content = content() } var body: some View { content } } From Swift 5.4, it can synthesize the init, so we can declare resultBuilder for stored property struct AwesomeContainerView<Content: View>: View { @ViewBuilder let content: Content var body: some View { content } } ...

February 24, 2021 · 1 min · Khoa Pham

How to tune performance with ButtonBehavior in SwiftUI

Issue #779 With Xcode 12.4, macOS 11.0 app. Every time we switch the system dark and light mode, the CPU goes up to 100%. Instruments show that there’s an increasing number of ButtonBehavior Suspect State in a row in LazyVStack Every cell has its own toggle state struct Cell: View { enum ToggleState { case general case request case response } let item: Item @State private var toggleState: ToggleState = ....

February 24, 2021 · 1 min · Khoa Pham

How to use GroupBox in SwiftUI

Issue #778 For now using GroupBox has these issues in macOS Prevents dragging scroll indicator to scroll Switch from light to dark mode may cause 100% CPU usage ...

February 23, 2021 · 1 min · Khoa Pham

How to suppress selector warning in Swift

Issue #777 Sometimes we need to use dynamic selector and that triggers warning in Swift Selector("updateWithCount:") // Use '#selector' instead of explicitly constructing a 'Selector' In ObjC we can use clang macro to suppress, like below #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void) deprecated_objc_method_override { } #pragma clang diagnostic pop But in Swift, we can just use a dummy NSObject that has the needed methods, like...

February 18, 2021 · 1 min · Khoa Pham

How to make simple search bar in SwiftUI

Issue #776 We need to use a custom Binding to trigger onChange as onEditingChanged is only called when the user selects the textField, and onCommit is only called when return or done button on keyboard is tapped. import UIKit import SwiftUI import EasySwiftUI struct SearchBar: View { @Binding var searchText: String let onChange: () -> Void @State private var showsCancelButton: Bool = false var body: some View { return HStack { textField cancelButton } } private var searchTextBinding: Binding<String> { Binding<String>(get: { searchText }, set: { newValue in DispatchQueue....

February 17, 2021 · 1 min · Khoa Pham

How to fix share and action extension not showing up in iOS 14

Issue #775 My share sheet and action extension not showing up in iOS 14, built-in Xcode 12.3. The solution is to restart test device, and it shows up again. Also make sure your extension targets have the same version and build number, and same deployment target <dict> <key>NSExtensionAttributes</key> <dict> <key>NSExtensionActivationRule</key> <dict> <key>NSExtensionActivationDictionaryVersion</key> <integer>2</integer> <key>NSExtensionActivationSupportsText</key> <true/> <key>NSExtensionActivationSupportsWebURLWithMaxCount</key> <integer>1</integer> <key>NSExtensionActivationSupportsWebPageWithMaxCount</key> <integer>1</integer> </dict> <key>NSExtensionJavaScriptPreprocessingFile</key> <string>MyPreprocessor</string> <key>NSExtensionActivationUsesStrictMatching</key> <integer>2</integer> </dict> ...

February 17, 2021 · 1 min · Khoa Pham

How to add home screen quick action in SwiftUI

Issue #774 Start by defining your quick actions. You can use UIApplicationShortcutIcon(type:) for predefined icons, or use UIApplicationShortcutIcon(systemImageName:) for SFSymbol enum QuickAction: String { case readPasteboard case clear var shortcutItem: UIApplicationShortcutItem { switch self { case .readPasteboard: return UIApplicationShortcutItem( type: rawValue, localizedTitle: "Read Pasteboard", localizedSubtitle: "", icon: UIApplicationShortcutIcon(type: .add), userInfo: nil ) case .clear: return UIApplicationShortcutItem( type: rawValue, localizedTitle: "Clear Pasteboard", localizedSubtitle: "", icon: UIApplicationShortcutIcon(systemImageName: SFSymbol.wind.rawValue), userInfo: nil ) } } } Add a service to store selected quick action....

February 10, 2021 · 2 min · Khoa Pham