Skip to content

Instantly share code, notes, and snippets.

View groue's full-sized avatar

Gwendal Roué groue

View GitHub Profile
@groue
groue / ObservableState.swift
Last active April 23, 2024 17:44
WithBindable
import SwiftUI
/// Supplies an observable object to a view’s hierarchy.
///
/// The purpose of `WithBindable` is to make it possible to instantiate
/// observable objects from environment values, while keeping the object
/// alive as long as the view is rendered.
///
/// For example:
///
@groue
groue / SynchronizationQueue.swift
Created February 14, 2024 13:12
A Swift concurrency queue that I find useful when dealing with synchronization.
import Semaphore
/// The priority of an operation started by `SynchronizationQueue`.
enum SynchronizationPriority {
/// An operation with `required` priority is not cancelled by
/// subsequent operations.
case required
/// Intended for "pull-to-refresh": an operation with `refresh` priority
/// is cancelled by subsequent operations started with the `refresh` or
@groue
groue / Trigger.swift
Created February 14, 2024 12:27
A Trigger type that helps SwiftUI views control when cancellable async jobs are run.
import SwiftUI
extension View {
/// Adds a task to perform before this view appears or when the trigger
/// is fired.
///
/// This method behaves like `View.task(id:priority:_:)`, except that it
/// cancels and recreates the task when the `fire` method of the
/// trigger is called.
///
@groue
groue / JSONSupportTests.swift
Created October 7, 2023 09:28
Test JSON support
import XCTest
import GRDB
class JSONSupportTests: GRDBTestCase {
func testJSONSupport() throws {
let queries = [
#"select json('[]') = '[]';"#,
#"select json_array() = '[]';"#,
#"select json_array_length('[]') = 0;"#,
#"select json_array_length('[[]]','$[0]') = 0;"#,
@groue
groue / opinion.md
Last active September 7, 2023 14:59
Swift key paths are not coding keys, JSON keys, or SQLite columns

Swift key paths are not coding keys, JSON keys, or SQLite columns

(Copy-pasted from groue/GRDB.swift#1423 (comment), edited for clarity)

And if I remember correctly, you had some good reasons for not using key paths in the GRDB query builder

My reluctance about key paths is based on the fact that record types do frequently, but not always, exactly reflect their database representation. The reality is that record types are a Swift interface to their inner database representation. And it's the same for "json records" as well.

That's how people use them. They'll replace a text database value with a Swift string-based enum value. They'll publicly expose a price: Decimal property instead of the priceCents database integer. They'll publicly expose a location: CLLocationCoordinate2D property instead of two latitude and longitude database doubles.

@groue
groue / transcript.md
Last active March 26, 2023 13:05
ChatGPT attempts at implementing a counting semaphore with Swift Concurrency

Is it possible to implement a classical counting semaphore with Swift concurrency (async/await)? I wish I could call an async method await semaphore.wait() and a sync method semaphore.signal() with the same semantics as a classical semaphore, but without blocking any thread.

Yes, it is possible to implement a classical counting semaphore with Swift concurrency using async/await without blocking any thread. Here is an example implementation: swift

class Semaphore {
    private var count: Int
    private let lock = NSLock()
    private var waiters: [Task<Void, Never>] = []
@groue
groue / TimestampedRecord.swift
Last active February 21, 2023 07:09
TimestampedRecord: an example protocol for GRDB records that track their creation and modification dates.
/// A type that tracks its creation and modification dates, as described in
/// <https://swiftpackageindex.com/groue/grdb.swift/documentation/grdb/recordtimestamps>
protocol TimestampedRecord {
var creationDate: Date? { get set }
var modificationDate: Date? { get set }
}
extension TimestampedRecord where Self: MutablePersistableRecord {
/// Sets `modificationDate` to the transaction date.
mutating func touch(_ db: Database) throws {
@groue
groue / Playground.swift
Last active September 28, 2022 15:54
Semaphore.swift
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
Task {
do {
print("Start, 1 concurrent task")
let semaphore = Semaphore(value: 1)
await withThrowingTaskGroup(of: Void.self) { group in
for i in 0..<10 {
group.addTask {
import SwiftUI
struct MyCollection: RandomAccessCollection {
let startIndex = 0
let endIndex = 1000
subscript(index: Int) -> Int {
print("Access \(index)")
return index
}
}

Explicit Protocol Fulfillment

Introduction

This pitch introduces of a new keyword in front of declarations: conformance.

The conformance keyword means: "this declaration is intended by the programmer to fulfill a protocol requirement". Its presence is never required. However, when present, the program is ill-formed unless the declaration does match a protocol requirement.

For example: