Skip to content

Instantly share code, notes, and snippets.

import UIKit
class ShadowedSwitch: UISwitch {
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
actor Foo {
private var firstTask: Task<Void, Error>?
func performFirstTask() async throws {
// create unstructured concurrency
let task = Task {
try await … // the work associated with first task
}
private func stream() -> AsyncThrowingStream<SomeData, Error> {
AsyncThrowingStream<SomeData, Error> { continuation in
let streamTask = Task {
do {
while !Task.isCancelled {
guard let message = try await self.task?.receive() else {
throw APIError.genericError
}
Self.logger.trace("\(SocketStrings.streamMessageYielded())")
extension ImageDownloader {
// if you don't care about the order
func downloadInRandomOrder() async -> [Image] {
await withTaskGroup(of: Image.self) { group in
let items = await fetchList()
for item in items {
group.addTask { await self.fetch(imageName: item.imageName) }
}
func foo() async {
await first()
if await second() {
// there several ways to run 3 and 4 in parallel; `async let`, shown here, is good pattern for fixed number of tasks; `TaskGroup` is good for variable number of tasks; both patterns keep you within realm of structured concurrency
async let thirdTask: () = third()
async let fourthTask: () = fourth()
await thirdTask
await fourthTask
} else {
// if 5 & 6 must run sequentially, then await 5 and then await 6
@robertmryan
robertmryan / CollateTasks.swift
Created January 28, 2024 16:02
Two common patterns for performing series of tasks in parallel, but collating the results into either an array or dictionary
extension Sequence where Element: Hashable & Sendable {
func dictionary<T: Sendable>(block: @escaping @Sendable (Element) async -> T) async -> [Element: T] {
await withTaskGroup(of: (Element, T).self) { group in
for id in self {
group.addTask { (id, await block(id)) }
}
return await group.reduce(into: [:]) { $0[$1.0] = $1.1 }
}
}
import SwiftUI
import AsyncAlgorithms
import os.log
private let poi = OSSignposter(subsystem: "MyApp", category: .pointsOfInterest)
typealias AsyncClosure = () async -> Void
struct ExperimentView: View {
@StateObject var viewModel = ExperimentViewModel()
func addSublayers(to view: UIView) {
let radius: CGFloat = 150
let borderWidth: CGFloat = 10
let circleCenterOffset: CGFloat = 120
let startCenter = CGPoint(x: 200, y: 200)
for i in 0..<3 {
let shapeLayer = createShapeLayer()
shapeLayer.path = circleDifference(
center: point(startCenter, xOffset: CGFloat(i) * circleCenterOffset),
@robertmryan
robertmryan / URLSession+AsyncAwaitCompatibility.swift
Created December 31, 2023 23:06
An async-await interface for URLSession with support for iOS 13 and later; unnecessary if minimum target is iOS 15 or later
//
// URLSession+AsyncAwaitCompatibility.swift
//
// Copyright © Robert M. Ryan. All Rights Reserved.
import Foundation
import os.log
private let log = OSLog(category: "URLSession+AsyncAwaitCompatibility")
class ViewController: UIViewController {
private var task: Task<Void, Never>?
override func viewDidLoad() {
super.viewDidLoad()
let task = Task {
do {
try await self.test()
} catch is CancellationError { // this is another way to check for `CancellationError`