How to parse large JSON Dictionary in Swift

Issue #865 We can define some typealias and build extensions on JSONDictionary to easily extract values typealias JSONDictionary = [String: Any] typealias JSONArray = [JSONDictionary] extension JSONDictionary { func dict(_ key: String) -> JSONDictionary? { self[key] as? JSONDictionary } func array(_ key: String) -> JSONArray? { self[key] as? JSONArray } func value<T>(_ key: String, as: T.Type) -> T? { self[key] as? T } } let responseJson = try JSONSerialization.jsonObject(with: data, options: []) guard let responseJson = responseJson as?...

February 7, 2022 路 1 min 路 Khoa Pham

How to make simple async URLSession in Swift

Issue #864 Since async is available in iOS 15+, we can build a custom one with withCheckedThrowingContinuation import UIKit enum HTTPMethod: String { case get = "GET" case post = "POST" } extension URLSession { func asyncData( with url: URL, method: HTTPMethod = .get, headers: [String: String] = [:], body: Data? = nil ) async throws -> Data { var request = URLRequest(url: url) request.httpMethod = method.rawValue request.allHTTPHeaderFields = [ "Content-Type": "application/json" ] request....

February 7, 2022 路 1 min 路 Khoa Pham

How to check SPL token balance on Solana

Issue #863 We will check USDC token balance on Solana testnet. Firstly, we will use to airdrop some USDC tokens into our wallet. Secondly, we check USDC token mint address on testnet cluster using Solana Explorer Then we make an RPC call to POST https://api.testnet.solana.com using method getTokenAccountsByOwner, passing our wallet address and the token mint address { "jsonrpc": "2.0", "id": 1, "method": "getTokenAccountsByOwner", "params": [ "53THxwqa9qF3cn46wHVKbGMM8hUpZDJE5jS3T1qVL5bc", { "mint": "CpMah17kQEL2wqyMKt3mZBdTnZbkbfx4nqmQMFDP5vwp" }, { "encoding": "jsonParsed" } ] } The response looks like below....

February 7, 2022 路 2 min 路 Khoa Pham

How to learn Solana programming

Issue #862 General Transaction Token program

February 7, 2022 路 1 min 路 Khoa Pham

How to use subscript in Swift

Issue #861 Make it easy to access common cases, for example UserDefaults extension UserDefaults { enum Key: String { case hasBackup } subscript(key: Key) -> Bool { get { bool(forKey: key.rawValue) } set { set(newValue, forKey: key.rawValue) } } } UserDefaults.standard.hasBackup] = true

February 5, 2022 路 1 min 路 Khoa Pham

How to encode JSON dictionary into JSONEncoder

Issue #860 JSONEncoder deals with type-safe, so we need to declare an enum JSONValue for all possible types. We also need a custom initializer to init JSONValue from a JSON Dictionary import Foundation enum JSONValue { case string(String) case int(Int) case double(Double) case bool(Bool) case object([String: JSONValue]) case array([JSONValue]) } extension JSONValue: Encodable { public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .string(let string): try container....

February 4, 2022 路 2 min 路 Khoa Pham

How to parse Apple Pay PKPayment in Swift

Issue #859 To parse PKPayment and used with Wyre CreateAppleOrder API, we can declare some Encodable structs import PassKit import Foundation struct PaymentObject: Encodable { var billingContact: Contact? var shippingContact: Contact? var token: JSONValue } extension PaymentObject { struct Contact: Encodable { var addressLines: [String]? var country: String? var countryCode: String? var familyName: String? var givenname: String? var locality: String? var postalCode: String? var administrativeArea: String? var subAdministrativeArea: String? var subLocality: String?...

February 4, 2022 路 1 min 路 Khoa Pham

How to pop multiple level with NavigationView and NavigationLink in SwiftUI

Issue #858 Use isActive and isDetailLink(false) Use Introspect .introspectNavigationController { nav in self.nav = nav } Read more

January 27, 2022 路 1 min 路 Khoa Pham

How to generate Solana wallet acount in Swift

Issue #857 Use Solana.swift and Mnemonic seed phrase. For production, change endpoint to mainnet import UIKit import Solana import KeychainAccess enum SolanaError: Swift.Error { case accountFailed case unauthorized } final class SolanaClient { static let shared = SolanaClient() final class SolanaClient { static let shared = SolanaClient() private let solana: Solana private let accountStorage = KeychainAccountStorage() private let seedPharser = SeedPhraser() private let endpoint: RPCEndpoint = .devnetSolana private let network: NetworkingRouter init() { self....

January 26, 2022 路 2 min 路 Khoa Pham

How to use Apple Pay in iOS

Issue #856 Use PKPaymentRequest and PKPaymentAuthorizationViewController @MainActor final class WalletViewModel: NSObject, ObservableObject { var canMakePayments: Bool { PKPaymentAuthorizationViewController.canMakePayments() } func showApplePay(amount: Amount, from window: UIWindow) { let request = PKPaymentRequest() request.supportedNetworks = [, .discover, .masterCard, .visa] request.countryCode = "US" request.currencyCode = "USD" request.merchantIdentifier = "merchant.\(Bundle.main.bundleIdentifier!)" request.merchantCapabilities = .capability3DS let item = PKPaymentSummaryItem(label: "Add Cash", amount: amount.toNsDecimal) request.paymentSummaryItems = [item] guard let vc = PKPaymentAuthorizationViewController(paymentRequest: request) else { return } vc.delegate = self window....

January 17, 2022 路 1 min 路 Khoa Pham

How to show QR code in SwiftUI

Issue #855 Use CoreImage to generate QR image import SwiftUI import CoreImage.CIFilterBuiltins struct QRView: View { let qrCode: String @State private var image: UIImage? var body: some View { ZStack { if let image = image { Image(uiImage: image) .resizable() .interpolation(.none) .frame(width: 210, height: 210) } } .onAppear { generateImage() } } private func generateImage() { guard image == nil else { return } let context = CIContext() let filter = CIFilter....

January 15, 2022 路 1 min 路 Khoa Pham

How to not encode with Enum key in Swift

Issue #854 If you use enum case as key in Dictionary, JSONEncoder will encode it as Array. For example enum Vehicle: String, Codable { case car case truck } struct Container: Codable { var map: [Vehicle: String] } struct Container2: Codable { var map: [String: String] } let container = Container(map: [ .car: "Car 1" ]) let container2 = Container2(map: [ "car": "Car 1" ]) let data = try! JSONEncoder().encode(container) print(String(data: data, encoding: ....

January 10, 2022 路 2 min 路 Khoa Pham

How to disable with ButtonStyle in SwiftUI

Issue #853 With ButtonStyle, the disabled modifier does not seem to work, we need to use allowsHitTesting. import SwiftUI struct ActionButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { HStack { Text("Button") } .padding() .disabled(true) // does not work .allowsHitTesting(false) } } We need to call disabled outside, after buttonStyle. In case we have onTapGesture on the entire view, touching on that disabled button will also trigger our whole view action, which is not what we want....

December 4, 2021 路 1 min 路 Khoa Pham

How to query document id in array in Firestore

Issue #852 Supposed we have Book object struct Book: Identifiable, Codable, Hashable { @DocumentID var id: String? } We should use FieldPath instead of id for query let booksRef: CollectionReference = ... let ids: [String] = ... booksRef .whereField( FieldPath.documentID(), in: ids )

November 28, 2021 路 1 min 路 Khoa Pham

How to provide default Codable in Swift

Issue #851 Use DefaultValue to provide defaultValue in our property wrapper DefaultCodable public protocol DefaultValue { associatedtype Value: Codable static var defaultValue: Value { get } } public enum DefaultBy { public enum True: DefaultValue { public static let defaultValue = true } public enum False: DefaultValue { public static let defaultValue = false } } @propertyWrapper public struct DefaultCodable<T: DefaultValue> { public var wrappedValue: T.Value public init(wrappedValue: T.Value) { self....

October 23, 2021 路 1 min 路 Khoa Pham

How to use dynamic shape in SwiftUI

Issue #850 Erase with AnyShape struct AnyShape: Shape { init<S: Shape>(_ wrapped: S) { innerPath = { rect in let path = wrapped.path(in: rect) return path } } func path(in rect: CGRect) -> Path { return innerPath(rect) } private let innerPath: (CGRect) -> Path } extension Shape { func erase() -> AnyShape { AnyShape(self) } } Then we can use like private struct ContentView: View { var body: some View { ZStack { Color....

September 30, 2021 路 1 min 路 Khoa Pham

How to use Picker with optional selection in SwiftUI

Issue #849 We need to explicitly specify optional in tag extension AVCaptureDevice: Identifiable { public var id: String { uniqueID } } @State var device: AVCaptureDevice? Picker("Camera", selection: $device) { ForEach(manager.devices) { d in Text(d.localizedName) .tag(AVCaptureDevice?.some(d)) } }

September 30, 2021 路 1 min 路 Khoa Pham

How to deinit NSWindow

Issue #848 Hold a weak reference to NSWindow, and let system window server manages its lifetime weak var window = NSWindow() window.isReleasedWhenClosed = true

September 9, 2021 路 1 min 路 Khoa Pham

How to scale system font size to support Dynamic Type

Issue #847 We should use Dynamic Font Type as much as possible, as per Typography guide and But in case we have to use a specific font, we can scale it with UIFontMetrics import SwiftUI import UIKit extension Font { static func system( scaledSize size: CGFloat, weight: Font.Weight = .regular, design: Font.Design = .default ) -> Font { Font.system( size: UIFontMetrics.default.scaledValue(for: size), weight: weight, design: design ) } } Then instead of...

September 2, 2021 路 1 min 路 Khoa Pham

How to round specific corner in SwiftUI

Issue #846 We use UIBezierPath with addArc to draw specific corner with different rounding values. import SwiftUI extension View { func clipCorners( topLeft: CGFloat = 0, bottomLeft: CGFloat = 0, topRight: CGFloat = 0, bottomRight: CGFloat = 0 ) -> some View { clipShape( SpecificCornerShape( topLeft: topLeft, bottomLeft: bottomLeft, topRight: topRight, bottomRight: bottomRight ) ) } } struct SpecificCornerShape: Shape { var topLeft: CGFloat = 0 var bottomLeft: CGFloat = 0 var topRight: CGFloat = 0 var bottomRight: CGFloat = 0 func path(in rect: CGRect) -> Path { let minX = rect....

August 26, 2021 路 2 min 路 Khoa Pham