How to open app with Control Widget on iOS 18

Issue #983 In iOS 18, we can make Control Widget in Widget extension import WidgetKit import SwiftUI @available(iOS 18.0, *) struct BookControlWidget: ControlWidget { var body: some ControlWidgetConfiguration { StaticControlConfiguration(kind: "Book") { ControlWidgetButton(action: BookIntent()) { Label("Book", systemImage: "airplane") } } .displayName("Book") } } import AppIntents @available(iOS 18.0, *) struct BookIntent: AppIntent { static let title: LocalizedStringResource = "Book" static var openAppWhenRun = true static var isDiscoverable = true func perform() async throws -> some IntentResult & OpensIntent { let url = URL(string: "myapp://book")!...

September 25, 2024 · 2 min · 389 words · Khoa

How to detect Barcode and QR code

Issue #973 Before iOS 11, we used to use CIDetector and CIDetectorTypeQRCode to detect QR code CIDetector An image processor that identifies notable features, such as faces and barcodes, in a still image or video. CIDetectorTypeQRCode A detector that searches for Quick Response codes (a type of 2D barcode) in a still image or video, returning CIQRCodeFeature objects that provide information about detected barcodes. func readQrOnly(image: CGImage) async -> String? { let ciImage = CIImage(cgImage: image) let detector = CIDetector( ofType: CIDetectorTypeQRCode, context: nil, options: [ CIDetectorAccuracy: CIDetectorAccuracyHigh ] ) guard let detector = detector else { return nil } let features = detector ....

June 6, 2024 · 2 min · 271 words · Khoa

How to make swifty UserDefaults

Issue #972 We want to have a swifty UserDefaults API that works with subscript and in a type safe manner. extension Defaults.Keys { static let string = Defaults.Key("string", default: "0") } XCTAssertEqual(defaults[.string], "0") defaults[.string] = "1" XCTAssertEqual(defaults[.string], "1") UserDefaults plist compatibility Define Compatible protocol that allows value to be plist compatible The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects....

May 28, 2024 · 3 min · 504 words · Khoa

How to escape characters in json and regex with Swift string

Issue #963 In the world of Swift programming, we often come across situations where we need to work with string literals that contain special characters. These characters can include new lines, tabs, backslashes, and quotes — all of which need to be handled appropriately to ensure they don’t inadvertently affect the structure or behavior of our code. Traditionally, we negate their special meaning by escaping them with backslashes. However, Swift provides an even simpler method — raw strings....

January 12, 2024 · 4 min · 812 words · Khoa

Building an iOS camera calculator with Core ML’s Vision and Tesseract OCR

Issue #960 Also written on Fritz Math might be scary, but it’s an essential part of everyday life. Wouldn’t it be cool if we could build an app, point our phone’s camera at an expression, and let the app compute the result? Whenever I’ve needed to use math, I’ve wished this was possible. Now, with advances in machine learning and vision recognition in iOS, this is doable. In this guide, I’ll provide some of the technical details for working with Vision in iOS, as well as my personal experiences using this technology....

December 31, 2023 · 12 min · 2460 words · Khoa

How to handle log in JSContext with JavascriptCore

Issue #957 Define console object and set log function to point to our Swift function import JavaScriptCore extension JSContext { func injectConsoleLog() { evaluateScript( """ var console = {}; """ ) let consoleLog: @convention(block) (Any) -> Void = { print($0) } objectForKeyedSubscript("console") .setObject(consoleLog, forKeyedSubscript: "log" as NSString) } } Then we can just call let context = JSContext()! context.injectConsoleLog() context.evaluateScript(jsContent)

December 7, 2023 · 1 min · 60 words · Khoa

How to make attributed TextView for macOS and iOS with SwiftUI

Issue #956 macOS import Foundation import SwiftUI import AppKit struct AttributedTextView: NSViewRepresentable { @Binding var attributedText: NSAttributedString var isEditable: Bool = true final class Coordinator: NSObject { let parent: AttributedTextView init( parent: AttributedTextView ) { self.parent = parent super.init() } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeNSView(context: Context) -> NSScrollView { let view = NSTextView.scrollableTextView() if let textView = view.documentView as? NSTextView { textView.font = NSFont.preferredFont(forTextStyle: ....

December 7, 2023 · 2 min · 257 words · Khoa

Apple Developer Learning resources

Issue #955 Besides WWDC videos & documentation, Apple also has interactive tutorials and books. Below are some of my favorites learning resources Tutorials Introducing SwiftUI: SwiftUI is a modern way to declare user interfaces for any Apple platform. Create beautiful, dynamic apps faster than ever before. Develop apps for iOS: Learn the basics of Xcode, SwiftUI, and UIKit to create compelling iOS apps. Develop in Swift: Develop in Swift Tutorials are a great first step toward a career in app development using Xcode, Swift, and SwiftUI....

November 29, 2023 · 1 min · 106 words · Khoa

How to update widget for iOS 17

Issue #948 iOS 17 has a new Stand by mode so SwiftUI introduces containerBackground for the system to decide when to draw background. It also automatically applies margin to widget so we may need to disable that To update existing widgets, we can write some useful extension extension View { @ViewBuilder func safeContainerBackground(@ViewBuilder content: () -> some View) -> some View { if #available(iOS 17.0, *) { self.containerBackground(for: .widget, content: content) } else { self....

October 2, 2023 · 1 min · 155 words · Khoa

How to move Core Data database to AppGroup folder

Issue #938 To let app and extension to talk to the same database, we need to use AppGroup. Here is how to use replacePersistentStore Replaces one persistent store with another actor DatabaseMigrator { @AppStorage("DatabaseMigrator.hasMigrated") var hasMigrated = false func migrateIfNeeded() { guard !hasMigrated else { return } migrate() hasMigrated = true } private func migrate() { let oldContainer = NSPersistentCloudKitContainer(name: "Bookmarks") guard let oldStoreUrl = oldContainer.persistentStoreDescriptions.first?.url, let newStoreUrl = Constants.appGroup.folderUrl?.appendingPathComponent(oldContainer.name + "....

July 30, 2023 · 1 min · 183 words · Khoa

How to read write files to iCloud Drive

Issue #937 First, you need to enable iCloud Documents capability. Go to target settings -> Signing & Capabilities -> iCloud ` Then inside your Info.plist, add this with your iCloud identifier and app name <key>NSUbiquitousContainers</key> <dict> <key>iCloud.com.onmyway133.PastePal</key> <dict> <key>NSUbiquitousContainerIsDocumentScopePublic</key> <true/> <key>NSUbiquitousContainerName</key> <string>PastePal</string> <key>NSUbiquitousContainerSupportedFolderLevels</key> <string>Any</string> </dict> </dict> To access to your iCloud Drive folder, we use FileManager to retrieve the folder. Returns the URL for the iCloud container associated with the specified identifier and establishes access to that container....

July 28, 2023 · 2 min · 296 words · Khoa

How to use keychain in Swift

Issue #934 There are a few keychain wrappers around but for simple needs, you can write it yourself Here is a basic implementation. I use actor to go with async/await, and a struct KeychainError to contain status code in case we want to deal with error cases. accessGroup is to define kSecAttrAccessGroup to share keychain across your apps public actor Keychain { public struct KeychainError: Error { let status: OSStatus } let service: String let accessGroup: String?...

July 20, 2023 · 2 min · 389 words · Khoa

How to make share and action extension in iOS

Issue #932 Add Share extension and Action extension respectively in Xcode. We can use the same code to both extension SwiftUI I usually make a ShareView in SwiftUI with ShareViewModel to control the logic struct ShareView: View { @ObservedObject var vm: ShareViewModel var body: some View { NavigationStack(path: $vm.routes) { List {} } } } In ShareViewController, we can just conform to UIViewController and add our SwiftUI view as child view controller...

July 12, 2023 · 2 min · 264 words · Khoa

AppStore screenshots size checklist

Issue #931 AppStore screenshots Screenshot specifications iPhone 6.7" Portrait 1290 x 2796 iPhone 6.5" Portrait 1242 x 2688 In-App Purchase screenshots In-app purchase information iOS 640 x 920 tvO 1920 x1080 pixels macOS 1280 x 800 pixels

July 12, 2023 · 1 min · 37 words · Khoa

How to use AppIntents in iOS 16

Issue #930 AppIntents Declare AppShortcutsProvider, note that appShortcuts uses @AppShortcutsBuilder syntax import AppIntents struct OurShortcutsProvider: AppShortcutsProvider { static var shortcutTileColor: ShortcutTileColor = .lightBlue @AppShortcutsBuilder static var appShortcuts: [AppShortcut] { AppShortcut(intent: AskIntent(), phrases: [ "Hey Joy", "Ask \(.applicationName)" ]) } } We can create an app intent in code import AppIntents import OpenAI struct AskIntent: AppIntent { static var title: LocalizedStringResource = "Hey Joy" static var description: IntentDescription = "Ask me anything" @Parameter(title: "Prompt") var prompt: String?...

July 11, 2023 · 1 min · 195 words · Khoa

SwiftUI EnvironmentValues

Issue #922 EnvironmentValues Views in SwiftUI can react to configuration information that they read from the environment using an Environment property wrapper Updated for iOS 17

June 21, 2023 · 1 min · 26 words · Khoa

How to make TextField Stepper in SwiftUI

Issue #921 Use HStack with TextField and a little extension extension Binding where Value == Int { var toString: Binding<String> { Binding<String>( get: { "\(wrappedValue)" }, set: { wrappedValue = Int($0) ?? 0 } ) } } struct TextFieldStepper: View { @Binding var value: Int var body: some View { HStack(spacing: 0) { TextField("", text: $value.toString) .textFieldStyle(.roundedBorder) .frame(width: 50) Stepper("", value: $value) } } }

June 20, 2023 · 1 min · 65 words · Khoa

How to clear TextEditor background in SwiftUI

Issue #920 For iOS 16 and macOS 13.0 TextEditor(text: $text) .scrollContentBackground(.hidden) For below, use [SwiftUI-Introspect](https://github.com/siteline/SwiftUI-Introspect) TextEditor(text: $text) .instrospectTextView { $0.drawsBackground = false }

June 19, 2023 · 1 min · 23 words · Khoa

Learning Metal for SwiftUI

Issue #919 WWDC23 introduces lots of new additions to SwiftUI, notably Metal shader support with these modifiers colorEffect: Returns a new view that applies shader to self as a filter effect on the color of each pixel. layerEffect: Returns a new view that applies shader to self as a filter on the raster layer created from self. distortionEffect: Returns a new view that applies shader to self as a geometric distortion effect on the location of each pixel....

June 16, 2023 · 3 min · 430 words · Khoa

WWDC23 SwiftUI Q&A

Issue #918 Interesting SwiftUI Q&A during WWDC23 Observable vs ObservableObject Q: With the new SwiftUI @Observable macro, are there any cases where ObservableObject would still be a better alternative? A: Use ObservableObject when you need to back deploy to before iOS 17 A: SwiftUI registers dependencies is a value is read during the evaluation of body. Indirect modifications should invalidate the dependencies. containerRelativeFrame in ScrollView Q: For the containerRelativeFrame, does that work cleanly in a List as well as a ScrollView?...

June 12, 2023 · 27 min · 5575 words · Khoa