Instead of:
.unsafeFlags(["-enable-upcoming-feature", "NonisolatedNonsendingByDefault"])
Use:
.enableUpcomingFeature("NonisolatedNonsendingByDefault")
I’ve found that Xcode will just silently let invalid Package.swift build.
Instead, make changes and then:
sudo xcode-select -switch /Applications/Xcode-version.app
swift package resolve
swift build
Introduced in Swift 6.2, -enable-upcoming-feature
NonisolatedNonsendingByDefault changes the execution semantics of nonisolated
async functions to always run on the caller’s actor by default. A new
@concurrent attribute can be added in order to specify that a function must
always switch off of an actor to run.
Source: https://docs.swift.org/compiler/documentation/diagnostics/nonisolated-nonsending-by-default/
Don’t assume that reference types should be sendable. Instead, try to remove concurrency.
Try to prevent them from crossing isolation boundaries in the first place.
Refernces:
https://youtu.be/N5iIXwBW54A?t=1205
and 20:30 here: https://developer.apple.com/videos/play/wwdc2025/268/
Create a copy of the value I need in the closure’s capture list. E.g.
@MainActor
struct MyView: View {
@State private var pulse = false
var body: some View {
Text("hi")
.visualEffect { [pulse] content, _ in
content.blur(radius: pulse ? 2 : 0)
}
}
}
Example from “Explore concurrency in SwiftUI” 2025
await withTaskGroup { group in
for thing in things {
group.addTask {
return await expensiveWork(on: thing)
}
}
for await result in group {
// Do something with each result
}
}
Example from “Elevate an app with Swift concurrency” 2025
Script to demonstrate @concurrent nonisolated
. Note that f
and g
are not marked async
, yet I can async let
them.
@concurrent
nonisolated func foo() async -> Int {
async let f = f()
async let g = g()
return await f + g
}
func f() -> Int {
print(Thread.current)
return 1
}
func g() -> Int {
print(Thread.current)
return 2
}
Task {
print(await foo()) // Prints 3
}
RunLoop.current.run()
I opened a question about this here: https://forums.swift.org/t/using-async-let-with-synchronous-functions/81907
In swift they are called ‘module-scoped’ functions
nonisolated
isn’t a hint to the compiler that the function isn’t protected!
This is all the swift book has to say about nonisolated:
Actors can also have nonisolated members,
whose declarations are marked with the `nonisolated` keyword.
A nonisolated member executes like code outside of the actor:
It can't interact with any of the actor's isolated state,
and callers don't mark it with `await` when using it.
This is inconsistent with Doug Gregor’s take in “Embracing Swift Concurrency” wwdc 2025:
nonisolated code is very flexible, because you can call it from anywhere.
If you call it from the main actor, it will stay on the main actor. If you
call it from a background thread, it will stay on a background thread.
And Massicotte’s understanding is that marking an async function
nonisolated and calling it from the main actor guarantees that it will not be
run on the MainActor. I’m not sure if that conclusion is warranted.
In my tests, though, it seems to be true but you have to follow the pattern
of making the _go()
function async. I.e. you can’t just mark the function nonisolated
and expect it to run off the main thread.
@MainActor
final class C {
func go() {
Task {
await expensive()
}
}
nonisolated func expensive() async {
MainActor.assertIsolated() // Traps, as we want
}
}
In his article, he says: “we’ve now made a function that is guaranteed to not be on the MainActor”
https://www.massicotte.org/step-by-step-network-request
There is one addition that 2025 session “Elevate an app with swift concurrency” makes at min 14.
Instead of nonisolated
she uses @concurrent nonisolated
, which removes the ambiguity.
Note that @concurrent requires that the fn is async (which expensive is).
I.e. I can have nonisolated func fn()
but not @concurrent nonisolated fn()
.
await withTaskGroup
is structured concurrency, just like async let.
Use it instead of Task and Task.detached if possible.
When to use:
- Known number of child concurrent tasks -> Use async let
- Unknown/dynamic number of child concurrent tasks -> Use TaskGroup
Tasks do inherit actor isolation. Task.detached do not:
@MainActor
class C {
var thisIsIsolated = “hi”
func f() {
Task {
print(self.thisIsIsolated) // No need to await here. On the main executor
MainActor.assertIsolated()
}
Task.detached {
print(self.thisIsIsolated) // Throws a compiler error
MainActor.assertIsolated() // Traps at runtime
}
}
}
Rob says “And note that in Task {…} in viewDidLoad, the @MainActor in is redundant. The UViewController is isolated to the main actor, as are its methods in your subclass, so the Task is already isolated to the main actor.”
Also, from https://www.massicotte.org/intro-to-isolation
@MainActor
class MyIsolatedClass {
func myMethod() {
Task {
// still isolated to the MainActor here!
}
Task.detached {
// explicitly non-isolated, regardless
// the enclosing scope
}
}
}
And a fun one that I didn’t anticipate, but makes sense since value types are copied:
// Does not compile with:
// Main actor-isolated property 'x' cannot be accessed from outside of the actor
@MainActor
class A {
var x = "x"
func fn() {
Task.detached {
self.x
}
}
}
// Compiles fine:
@MainActor
struct A {
var x = "x"
func fn() {
Task.detached {
self.x
}
}
}
Given the sequence
let sequence: any Sequence<Int> = [1,2,3]
If I do this:
for element in sequence {}
the sequences iterator will call next
and walk through the sequence until exhausted. So this is lazy by default.
Why does the .lazy
method exist then? It’s intended to prefix operations on the sequence that would normally eagerly compute the full result:
sequence.map { $0 * 2 }
That operation would call .next()
four times before returning. But:
sequence.lazy.map { $0 * 2 }
doesn’t call .next()
at all, until a consumer starts consuming the sequence. Then .next
is called lazily, as needed by the consumer
Find it at:
/Applications/Xcode-beta 2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/FoundationModels.framework/Modules/FoundationModels.swiftmodule/arm64e-apple-ios.swiftinterface
Find swift concurrency interface at
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/swift/_Concurrency.swiftmodule/arm64e-apple-ios.swiftinterface
These are called parameterized extensions, and they are not implemented in the language.
Workaround here:
https://forums.swift.org/t/extension-on-array-where-element-is-generic-type/10225/4
With primary associated types, Nate’s example can be simplified a touch to:
protocol Rangey<Bound> {
associatedtype Bound: Comparable
var range: Range<Bound> { get }
}
extension Range: Rangey {
var range: Range<Bound> { return self }
}
extension Array where Element: Rangey<Date> {
func contains(date: Date) -> Bool {
return contains(where: { $0.range.contains(date) })
}
}
Remember Range
is defined in the stdlib as:
public struct Range<Bound> where Bound : Comparable
Swift 5.7+ allows for some additional sugar with PATs.
But, while they look like generic parameters, they are not!
It’s still a PAT (protocol with associated type), but it has a “primary” associated type.
This gives us some sugar.
When we used to constrain an associated type on a function, something like:
func fn<S>(_ s: S) where S: Sequence, S.Element == Character {
var iterator = s.makeIterator()
if let x = iterator.next() {
print(x)
}
}
fn("abc")
// prints a
we can now write:
func fn<S>(_ s: S) where S: Sequence<Character> {
var iterator = s.makeIterator()
if let x = iterator.next() {
print(x)
}
}
Protocols do not have generic parameters:
“[protocols] don’t (and can’t) have generic parameters. Protocols just have associated types, whether primary or not.”
https://forums.swift.org/t/understating-primary-associated-types-in-swift-5-7/59916/4
Also, I don’t know if this used to be possible, but you can now constrain an existential using the primary associated type:
let sequence: Sequence<Int> = [1,2,3]
sequence.map { $0 * 2 }
vim /Library/Developer/CommandLineTools/SDKs/MacOSX15.5.sdk/System/iOSSupport/usr/lib/swift/Swift.swiftmodule/arm64e-apple-ios-macabi.swiftinterface
If you just want to get something done, Swift is not the language.
It has gone so far in the ‘advanced PL’ direction that when you use it you have two puzzles:
1. The problem that you are actually setting out to solve
2. The types and constraints puzzle that swift imposes on you
For large teams this burden can pay off, because the compiler’s role in keeping
the evolvoing codebase correct becomes meaningful.
For a startup that’s just trying to get domain ideas out to market, it really sucks.
^ Immediately after typing this up, I needed to create a queue. Should be easy enough, right?
I punch this into a repl:
struct Queue<T> {
var backing = [T]()
mutating func enqueue(_ item: T) {
backing.append(item)
}
mutating func dequeue() -> T? {
backing.popFirst()
}
}
And I get:
error: referencing instance method 'popFirst()' on 'Collection' requires the types '[T]' and 'Array<T>.SubSequence' (aka 'ArraySlice<T>') be equivalent
So now I need to scratch my head about the type puzzle.
Can I specify that [T]
and Array<T>.SubSequence
are equal?
And why is the error talking about [T]
instead of T
?
Then after some digging I find this:
extension Collection where Self == Self.SubSequence {
mutating func popFirst() -> Element?
}
meaning popFirst
is only defined on collections where the collection type is the same as the subsequence type. Ok? Does that apply to Array? No:
extension Array : RandomAccessCollection, MutableCollection {
public typealias SubSequence = ArraySlice<Element>
}
So now I’ve wasted a bunch of time puzzling over something that has nothing to do with my goal!
Weirdly, if you use popLast
instead of popFirst
it compiles just fine. I’m using Swift 6.1.2
If I implement my own Collection, and add the following:
struct MyCollection: Collection {
public typealias Index = Int
public var startIndex: Index { ... }
public var endIndex: Index { ... }
public subscript(i: Index) -> Base.Element { ... }
public func index(after i: Index) -> Index { ... }
}
I then get the full Collection and Sequence APIs at my disposal. On myCollection
I can now
allSatisfy
compactMap
drop(while:)
dropFirst
dropLast
firstIndex(of:)
firstIndex(where:)
flatMap
map
max
min
prefix
prefix(upTo:)
prefix(while:)
reversed
sorted(by:)
etc. etc.
That’s pretty cool.
Note from Dave Abrahams on conforming to Collection instead of Sequence:
Finally, because it is at the root of the protocol hierarchy and has so few
requirements, it is very attractive to implement Sequence where implementing
Collection would be more appropriate. Making a type conform to Sequence instead
of Collection has both efficiency and capability costs for operations on that
type.
A Collection
refines Sequence
, e.g. public protocol Collection<Element>: Sequence
From Apple’s docs, a collection is:
> A sequence whose elements can be traversed multiple times, nondestructively, and accessed by an indexed subscript.
It’s not String([1,2,3])
it’s String(describing: [1,2,3])
locate .swiftinterface | grep swiftuicore | grep iPhoneOS
There is both a SwiftUICore.swiftmodule and a SwiftUI.swiftmodule:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/arm64e-apple-ios.swiftinterface
Repl session.
protocol P {
func f()
}
func callF(_ p: P) {
p.f()
}
struct A: P {
func f() {
print("Hi from A")
}
}
callF(A()) // prints "Hi from A"
struct B: P {
func f() {
print("Hi from B")
}
}
callF(B()) // prints "Hi from B"
[A(), B()].forEach { callF($0) } // Compiler error
struct AnyP: P {
let base: P
init<U: P>(_ concrete: U) {
self.base = concrete
}
func f() {
self.base.f()
}
}
[AnyP(A()), AnyP(B())].forEach { callF($0) } // prints "Hi from A" followed by "Hi from B"
In the stdlib there are signatures like filter
on Sequence that uses rethrows:
@inlinable
public __consuming func filter(
_ isIncluded: (Element) throws -> Bool
) rethrows -> [Element] {
return try _filter(isIncluded)
}
It lets us call filter
without a try
:
[1,2,3].filter { $0 > 1 }
But with a try
if the argument can throw:
enum MyError: Error { case bad }
func fn(_ x: Int) throws -> Bool {
throw MyError.bad
}
do {
_ = try [1, 2, 3].filter(fn)
} catch {
print("Caught error: \(error)")
}
An @unchecked Sendable
is “A type whose values can safely be passed across concurrency domains by copying, but which disables some safety checking at the conformance site.”
Source: https://developer.apple.com/documentation/swift/unsafesendable
Versus a Sendable which is “A thread-safe type whose values can be shared across arbitrary concurrent contexts without introducing a risk of data races.”
Source: https://developer.apple.com/documentation/Swift/Sendable
When I see it in code, read it as ‘particular’ instead of ‘some’.
‘any’ is an existential. Relies on dynamic dispatch.
‘some’ is an opaque type to the caller, but still has identity that the compiler knows of.
Easiest to think of as ‘reverse generics’:
"An opaque return type can be thought of as putting the generic signature "to the right" of the
function arrow; instead of being a type chosen by the caller that the callee sees as
abstracted, the return type is chosen by the callee, and comes back to the caller as
abstracted"
Soruce: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0244-opaque-result-types.md
protocol X {
var y: String // this is a customization point
}
extension X {
var z: String {
“Not a customization point!”
}
// default implementation
var y: String {
"hello world"
}
}
// X#z can’t be customized, but X#y can
func makeStream() -> AsyncStream<Int> {
return AsyncStream { continuation in
let task = Task {
var n = 0
while !Task.isCancelled {
print("Sending", n)
continuation.yield(n)
try? await Task.sleep(nanoseconds: 1_000_000_000)
n += 1
}
print("Cancelled!")
}
continuation.onTermination = { _ in
task.cancel()
}
}
}
Source: https://forums.swift.org/t/why-asyncstream-breaks-structured-concurrency/71477/4
Swift gotcha: A Task
does not create a child task.
https://forums.swift.org/t/why-asyncstream-breaks-structured-concurrency/71477/3
Read all answers by robert.ryan in that thread
Visual on different ways to create a task:
https://forums.swift.org/t/should-task-groups-inherit-actor/57547/2
More info on the swift gotcha of a Task not creating a child task:
> Tasks created with Task are not child tasks of the current task, and
changes to the current task like cancellation and priority escalation are
not propagated to them. Task just copies more of the context of the current
task than Task.detached does.
> The only true child tasks (currently) are the tasks created by async let
and TaskGroup.
Source: https://forums.swift.org/t/calling-synchronous-function-with-async-let/59211/8
Handy when trying to conditionally compile a lib feature that is backdeployed
but not available for customers on older versions of Xcode:
Quinn the Eskimo: https://forums.swift.org/t/how-to-handle-errors-in-swift-when-coming-from-a-java-world/20821/13
struct S {
var x = 1
}
var y: [String: S] = ["a": S()]
y["a"]?.x = 2
y["a"]?.x // Returns 2!
I figured I would have to do this:
var y: [String: S] = ["a": S()]
y["a"] = S(x: 2)
The first snippet rewritten with an assignment does what I expect:
struct S {
var x = 1
}
var y: [String: S] = ["a": S()]
var z = y["a"]
z?.x = 2
y["a"]?.x // Returns 1
Returning to first snippet. Will didSet handlers get called with this setup:
struct S {
var x = 1
}
final class C {
var y: [String: S] = ["a": S()] {
didSet {
print("Am I called?")
}
}
func mutate() {
self.y["a"]?.x = 2
}
}
C().mutate()
// Prints "Am I called?"
“Marking something as nonisolated tells the compiler that you’re not going to touch any of the
isolated state and therefore this function can be called from anywhere”
https://developer.apple.com/videos/play/wwdc2021/10194/?time=2302
Quinn the Eskimo!
In Swift concurrency, tasks are run by threads from the Swift concurrency cooperative thread
pool. When a task suspends at an await, the thread running that task returns to the thread pool
and looks for more work to do.
https://developer.apple.com/forums/thread/708182
Structured tasks are canceled when they go out of scope (that means for async let
and await withTaskGroup
).
Unstructured tasks are canceled cooperatively, meaning it’s up to my code to check for either:
Task.isCancelled
or
try Task.checkCancellation
Another Quinn the Eskimo! gem: https://developer.apple.com/forums/thread/760725
actor MyActor {
func doStuff() {
Task { @MainActor in
MainActorState.counter += 1
}
}
}
Also notice how he annotates the static var below as @MainActor. You can’t apply that
annotation to the enclosing type:
enum MainActorState {
@MainActor static var counter: Int = 0
}
actor MyActor {
func doStuff() {
MainActorState.counter += 1
// ^ Main actor-isolated static property 'counter' can not
// be mutated on a non-isolated actor instance
}
}
Swift 6.2
Task { @concurrent in
// Do work
}
This does not isolate doSomething:
@globalActor public actor RealtimeActor {
public static let shared = RealtimeActor()
}
@RealtimeActor
final class Foo {
static func doSomething() {}
}
Try it in a sample project. You can call Foo.doSomething
outside of a task, and it will
execute on the main thread.
Ah, it’s by design
Static methods, properties, and subscripts do not have a self parameter that is an instance of the actor, so they are not actor-isolated.
https://github.com/swiftlang/swift-evolution/blob/main/proposals/0306-actors.md
https://x.com/nsobject/status/1892611473144213584
For functions that return void:
let d = Date()
async let parallelDep1: Void = wait1()
async let parallelDep2: Void = wait2()
_ = await (parallelDep1, parallelDep2)
print(String(format: "Deps loaded in %.2f seconds", Date().timeIntervalSince(d)))
private func wait1() async {
try? await Task.sleep(for: .seconds(1))
}
private func wait2() async {
try? await Task.sleep(for: .seconds(1))
}
Quinn the Eskimo! says:
My favourite trick for this problem in general is to add a pause() system call to the front of
my code. That stops the process until it receives a signal, and the act of attaching the
debugger generates that signal and thus you can just continue from there.
https://forums.swift.org/t/editing-and-debugging-a-swiftpm-plugin/71935/6
private static var myString: String {
get async {
return await getTheString()
}
}
try? await Task.sleep(nanoseconds: 1_000_000_000)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
print("hello")
}
// or
Task {
try? await Task.sleep(nanoseconds: 2_000_000_000)
print("world")
}
AI bad at POP. When to use customization points vs default extensions.
It can tell you what they are, but it won’t design w/ them. Yet.
From root of package:
swift package dump-package
From within the task:
try Task.checkCancellation()
if case let .longHTTP(wait: wait) = strategy {
request.addValue("Prefer", forHTTPHeaderField: "wait=\(wait)")
}
First, use Decodable. But if I’m roughing something in:
import Foundation
let myData: Data = ...
let deserialized = try JSONSerialization.jsonObject(with: myData)
guard let json = deserialized as? [String: Any] else {
throw MyError("Could not deserialize data to [String: Any]")
}
URLRequest comes with a default timeout of 60 seconds. Can catch timeouts with (see line 27):
https://gist.github.com/lzell/42b47aa5e521a3e20840aba093a7c835
It fails for properties that I have setup with acronyms, e.g.
struct Response: Decodable {
let fooURL // I want this to map to "foo_url"
}
The error:
"Unescaped control character '0xa' around line 3, column 0."
is due to an unescaped newline in a JSON field. Repro:
let response = """
{
"message": "will\nfail"
}
"""
struct Response: Decodable {
let message: String
}
_ = try! JSONDecoder().decode(Response.self, from: response.data(using: .utf8)!)
It’s actually Foundation that adds the localizedDescription property on an error. For example,
this fails in a repl:
enum MyError: Error {
case foo
}
do {
throw MyError.foo
} catch {
print(error.localizedDescription)
}
but if I import Foundation
first, it works as expected.
To modify the error description, use this:
import Foundation
enum MyError: LocalizedError {
case foo
var errorDescription: String? {
switch self {
case .foo:
return "My description"
}
}
}
do {
throw MyError.foo
} catch {
print(error.localizedDescription) // prints 'My description'
}
URLComponents are not needed to get out the domain and path.
let url = URL(string: "https://api.aiproxy.pro/foo/bar")!
Get the domain
url.host
Get the path
url.path
Error handling in Swift resembles exception handling in other languages, with the use of the
try, catch and throw keywords. Unlike exception handling in many languages — including
Objective-C — error handling in Swift doesn’t involve unwinding the call stack, a process that
can be computationally expensive. As such, the performance characteristics of a throw statement
are comparable to those of a return statement.
From: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling/
// A.swift
struct A {
}
// A+B.swift
extension A {
struct B {
}
}
I think it’s more common to use this pattern for protocol conformance, but I like it for nested
structs too. I searched around for examples of Apple code that uses this pattern. It’s in
swift-foundation:
https://developer.apple.com/documentation/foundation/date/iso8601formatstyle
https://github.com/apple/swift-foundation/blob/main/Sources/FoundationEssentials/Formatting/Date%2BISO8601FormatStyle.swift#L24
f
and g
are equivalent here:
protocol P {}
struct S: P {}
func f<T>(_ t: T) where T: P {}
func g<T: P>(_ t: T) {}
f(S())
g(S())
Apple calls the first syntax a ‘generic where clause’ and the second a ‘generic parameter
clause’. The only difference, as far as I can tell, is the where clause can support constraints
on a protocol’s associated types, e.g. where S1.Iterator.Element == S2.Iterator.Element
If I am not working with PATs, I prefer the syntax func g<T: P>(_ t: T)
struct S<T> {
let s: T
}
extension S where T == Int {
func plusOne() -> Int {
return self.s + 1
}
}
let x = S<Int>(s: 1)
print(x.plusOne()) // prints 2
Instead of
"{\"x\":\"y\"}"
Use
#"{"x":"y"}"#
For a multiline string that I don’t want to escape quotes or slashes:
#"""
This is
"cool"
"""#
See the ‘future proof’ section here: https://www.donnywals.com/writing-custom-json-encoding-and-decoding-logic/
Always name the associated value, otherwise you get a 0: "whatever"
in your encoded json.
The fact that I need to introduce type erasure for a concept this simple is still wild to me:
let dict = ["A": "x", "B": 2]
try? JSONEncoder().encode(dict) // Won't work
We had this with obj-c out of the box.
Redditor to the rescue: https://www.reddit.com/r/swift/comments/1ecv7dw/wrangling_json_in_swift/
let dict: [String: Any] = ["A": "x", "B": 2]
let data = try? JSONSerialization.data(withJSONObject: dict)
String(data: data!, encoding: .utf8)
Swift doesn’t have a sum or union. What do people use instead? Enum with associated values
Use the +
overload:
Data() + Data()
import Foundation
UUID().uuidString
FatalError
for broken invariants. Crash hard.AssertionError
and return nil[1,2,3].map { x in x + 1 }
[1,2,3].map { $0 + 1 }
RunLoop.current.run()
Codable is defined as
public typealias Codable = Decodable & Encodable
If I only want to create types that are encodable, use struct MyMessage: Encodable
import Foundation
struct S: Encodable {
let x: String
let y: Int
}
let s = S(x: "hello", y: 123)
let jsonData = JSONEncoder().encode(s)
if let jsonStr = String(data: jsonData, encoding: .utf8) {
print(jsonStr)
// prints {"x":"hello","y":123}
}
There is no guarantee of key order when structs are encoded. For unit tests,
create the encoder with the following for predictable serialization results:
let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys
Don’t put Tasks everywhere. Try to stay structured
(swift, stringify without using codable)
private func stringify(_ args: [String: Any]) -> Data? {
if JSONSerialization.isValidJSONObject(args) {
return try? JSONSerialization.data(withJSONObject: args, options: [])
}
return nil
}
(swift, remove from dictionary)
var x = ["a": 1]
x.removeValue(forKey: "a")
x #=> [:]
(swift, tuple destructuring)
var x = (1, "hello")
var (a, b) = x
a #=> 1
b #=> "hello"
(swift, special case for simulator)
#if targetEnvironment(simulator)
// Do something special
#endif
#if os(macOS)
print("mac")
#else
print("not mac")
#endif
(swift, dictionary, increment key, ruby ||=)
var x = String: Int
x[“a”, default: 0] += 1 // a maps to 1
x[“a”, default: 0] += 1 // a maps to 2
(swift async streams, continuations)
- AsyncStream conforms to AsyncSequence
- See the docstring on AsyncThrowingStream for modifying an existing
closure-based callback earthquake monitor into an async/await-compatible interface
- See continuation
reference in wwdc/modern_crash_course_takeaways.txt
- Sendable
is “A type whose values can safely be passed across concurrency domains by copying.”
- See ~/dev/ContinuationExperiment
(swift get type of instance)
type(of: myInstance)
(swift regex, repl)
Start the repl with:
swift repl -enable-bare-slash-regex
> var a = "a"
> let re = /a/
> a.replace(re) { match -> String in "b" }
> a
// Outputs "b"
What most languages call ‘lazy’ (i.e. ? after a pattern), swift calls ‘reluctant’:
See Swift Regex: Beyond the basics, 12:35
(swift regex, SPM)
Modify the target sections of Package.swift to look like this:
.target(
name: "AIProxySwift",
swiftSettings: [
.unsafeFlags(["-Xfrontend", "-enable-bare-slash-regex"])
]
),
.testTarget(
name: "AIProxySwiftTests",
dependencies: ["AIProxySwift"],
swiftSettings: [
.unsafeFlags(["-Xfrontend", "-enable-bare-slash-regex"])
]
),
@globalActor actor MyStickerActor {
static let shared = MyStickerActor()
}
// Then...
@MyStickerActor
func createSticker(_ prompt: String) async throws -> UIImage
(gcd notes, libdispatch notes, use it right, serial queue)
https://gist.github.com/tclementdev/6af616354912b0347cdf6db159c37057
(swift data)
How to create a model container outside of SwiftUI context:
https://developer.apple.com/documentation/swiftdata/preserving-your-apps-model-data-across-launches
References to organize:
// Meet SwiftData: https://developer.apple.com/videos/play/wwdc2023/10187/
// Build an App with Swift Data: https://developer.apple.com/videos/play/wwdc2023/10154
// https://developer.apple.com/xcode/swiftdata/
// bug: https://developer.apple.com/forums/thread/732788
//
// Swipe to delete: https://developer.apple.com/documentation/swiftdata/deleting-persistent-data-from-your-app
//
(swift, start repl)
swift repl
// Interpolation
let a = “a”
let a_ = “(a)”
a == a_ # => true
// Concatenation
a + “b” == “ab” # => true
// Printing multiple strings
print(a, “b”) # => prints “a b”
// Printing floats
import Foundation
let a = 1.2345
String(format: “%.2f”, a) # => 1.23
// Separating string variables from the string template:
import Foundation
String(format: “%@ %@”, “hello”, “world”)
Minute 27 of “modern swift API design”
(smells, protocol, overuse, protocols aren’t mixins)
Add to my talk: minute 13 of wwdc “modern swift API design”.
If conformer calls protocol definitions, you’re using it wrong.
(swift add convenience initializer to struct, keep memberwise initializer)
Add the initializer in an extension to avoid losing the default memberwise initializer
(swift demangle, stack trace, demangle)
xcrun swift-demangle
(assembly, swift)
For anyone curious how to look at assembly for snippets of swift, this is what
I ran: xcrun -sdk iphoneos swiftc -target arm64-darwin-ios11 -O -S -o - input.swift | xcrun swift-demangle | less
(repl, swift, lookup, type)
$ swift repl
> :type lookup String
Use this to search the api with fuzzy search (ctrl+6 once open):
printf “import Foundation:type lookup String” | swift > /tmp/foo.swift && open -a /Applications/Xcode.app /tmp/foo.swift
(repl, spm, swift, package, import module)
Start repl with:
$ swift build && swift -I.build/debug -L.build/debug -lBluetoothService
> import BluetoothService
(swift compiler, swiftc)
Additional help:
swiftc -help-hidden
(switch swift version)
$ sudo xcode-select -switch /Applications/Xcode-beta.app
$ xcrun swift –version
(swift, get type)
“foo”.dynamicType
(swift, initializers)
http://stackoverflow.com/questions/29956195/idiomatic-pattern-to-initialize-uiviews-in-swift
Will be able to find *-Swift.h in:
~/Library/Developer/Xcode/DerivedData/
Run with:
xcrun swift
or yosemite:
swift
or:
lldb –repl
When modifying previously entered input: insert newline with opt+enter
Type :help to get list of commands
:quit to quit
To set a breakpoint from within repl, create a function called go, then set a
breakpoint in the body with:
:breakpoint set –line
Then call go()
Emit debug information:
$ swiftc filename.swift -g
Run program with lldb:
$ lldb -f filename
Set breakpoint:
(lldb) breakpoint set –file filename.swift –line 1
Run:
(lldb) run
Print lots of information:
(lldb) fr v -R
Change the variable to nil:
(lldb) p x = nil
Dump it again:
(lldb) fr v -R x
(lldb) expression -l objc -O – (id) 0xaddressofobject