Skip to content

Instantly share code, notes, and snippets.

View ra9r's full-sized avatar

RA9R ra9r

View GitHub Profile
@ra9r
ra9r / Extension+UserDefaults.swift
Created September 25, 2022 11:36
Adding support for loading and saving JSON to UserDefaults
extension UserDefaults {
static func loadJSON<T>(forKey: String) -> T? {
let defaults = UserDefaults.standard
if let data = defaults.object(forKey: forKey) as? Data {
let decoder = JSONDecoder()
if let loadedData = try? decoder.decode(T.self, from: data) {
return loadedData
}
}
return nil
@ra9r
ra9r / CustomBGListExample.swift
Created September 26, 2022 04:07
This is how to change the background of a List. It is no longer necessary to reference UITableView.appearance().
// This is how to change the background of a List.
// It is no longer necessary to reference UITableView.appearance()
List {
// list content
}
.scrollContentBackground(.hidden) // <-------- Here is the magic
@ra9r
ra9r / CloudKitExample.swift
Created September 26, 2022 09:27
Cheatsheet for querying CloudKit
// Configuration
let identifier = "iCloud.{your-container-name}"
let token = "{your-token-generated-from-cloudkit-console}"
let container = CKWSContainer(identifier: identifier, token: token, enviornment: .development)
// Create an operation that queries all records of the "ExampleType"
let queryOperation = CKWSQueryOperation(query: CKWSQuery(recordType: "ExampleType"))
queryOperation.recordMatchedBlock = { recordID, result in
@ra9r
ra9r / FirebaseAuthRule.md
Created September 27, 2022 09:56
This is an example of how to restrict read, edit, update to content owner only.
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents/weight {
    match /{document=**} {
        allow write: if true;
      allow read, write, delete: if
          request.auth != null && request.auth.uid == d;
    }
 }
@ra9r
ra9r / KeychainStorage.swift
Created September 28, 2022 08:06
A property wrapper for Keychain storage
import SwiftUI
import KeychainAccess
@propertyWrapper
struct KeychainStorage<T: Codable>: DynamicProperty {
typealias Value = T
let key: String
@State private var value: Value?
init(wrappedValue: Value? = nil, _ key: String) {
@ra9r
ra9r / AuthModel.swift
Last active September 28, 2022 09:56
Example of how to authenticate with Biometrics
func signInWithBiometrics() {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Please authenticate yourself to unlock your places."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
if success {
Task { @MainActor in
@ra9r
ra9r / MultiComponentPicker.swift
Created October 2, 2022 00:55
Fix for Multi-Component Picker on iOS 16.0
//
// MultiComponentePicker.swift
// SwiftJourney
//
// Created by Rodney Aiglstorfer on 10/2/22.
//
import SwiftUI
struct MultiComponentePicker: View {
@ra9r
ra9r / sfrounded.swift
Created October 3, 2022 01:53
How to use SF Rounded Font in Swift UI
Text("Your Text").font(.system(.body, design: .rounded))
@ra9r
ra9r / ContentView.swift
Created October 8, 2022 01:08
Examples of reacting to changes in TextFields
struct ContentView : View {
@State var text1 = ""
@State var text2 = ""
@StateObject var model = ViewModel()
var body: some View {
TextField("Text 1", text: $text1)
{ editing in
print("Editing?: \(editing)")
} onCommit: {
@ra9r
ra9r / README.md
Created October 9, 2022 07:47
Loading different GoogleService-Info.plist for dev and prod environments

If the builds are part of a single target, the best option is to give both configuration files unique names (e.g. GoogleService-Info-Free.plist and GoogleService-Info-Paid.plist). Then choose at runtime which plist to load. This is shown in the following example:

// Load a named file.
let filePath = Bundle.main.path(forResource: "MyGoogleService", ofType: "plist")
guard let fileopts = FirebaseOptions(contentsOfFile: filePath!)
  else { assert(false, "Couldn't load config file") }
FirebaseApp.configure(options: fileopts)