I'm relatively new to Swift, and very new to concurrency via Async/Await, so please be patient. 😀
I'm having a hard time comprehending how to do complex operations asynchronously in background threads, and then in turn bring the results back to the main thread. I'm getting various errors along the lines of "Mutation of captured var 'personName' in concurrently-executing". I've paired the issue down as simply as possible as follows, and you'll see where the compiler gives the error message.
I'd appreciate any advice on how to evolve my mental model to make this work.
Thanks!
Bruce
import Foundation
actor Person {
var myName = "Thomas Jefferson"
var name: String {
get {
return myName
}
}
}
func main() {
let person = Person()
var personName: String
print("start")
let nameTask = Task {
return await person.name
}
Task {
do {
personName = try await nameTask.result.get()
// Error: Mutation of captured var 'personName' in concurrently-executing code
} catch {
print("error!!!")
}
}
print("The person's name is \(personName)")
}
RunLoop.main.run()
main()
Post
Replies
Boosts
Views
Activity
I'm continuing with the migration towards Swift 6. Within one of our libraries, I want to check whether a parameter object: Any? confirms to Sendable.
I tried the most obvious one:
if let sendable = object as? Sendable {
}
But that results into the compiler error "Marker protocol 'Sendable' cannot be used in a conditional cast".
Is there an other way to do this?
I have a custom localisation function in my project that enforces the inclusion of the bundle parameter (specifically so that Swift packages are forced to include the Bundle.module value).
While migrating to String Catalogs, I noticed that my custom localisation function wasn't being recognised by the automatic extraction that the Swift compiler is doing, but only in my Swift package targets.
Is there a way to set something like LOCALIZED_STRING_MACRO_NAMES in Swift Packages?
Hello,
I am working on a macOS Virtualization framework project on Xcode.
Is there a way to redirect an USB device connected to the host mac, to a virtual machine.
I know this is possible with lower layers but i would like to do it with a VZVirtualMachine object. Is it possible ?
Thanks
This is the error I am continuosly receiving.
Hey, im new here. And I need to share a variable between files, settings and home. I've searched all over and found solutions, but I just don't understand what to do.
Helo all,
Currently, I'm working on an iOS app that performs measurement and shows the results to the user in a graph. I use a Savitzky-Golay filter to filter out noise, so that the graph is nice and smooth. However, the code that calculates the Savitzky-Golay coefficients using sparse matrices crashes sometimes, throwing an EXC_BAD_ACCESS. I tried to find out what the problem is by turning on Address Sanitizer and Thread Sanitizer, but, for some reason, the bad access exception isn't thrown when either of these is on. What else could I try to trace back the problem?
Thanks in advance,
CaS
To reproduce the error, run the following:
import SwiftUI
import Accelerate
struct ContentView: View {
var body: some View {
VStack {
Button("Try", action: test)
}
.padding()
}
func test() {
for windowLength in 3...100 {
let coeffs = SavitzkyGolay.coefficients(windowLength: windowLength, polynomialOrder: 2)
print(coeffs)
}
}
}
class SavitzkyGolay {
static func coefficients(windowLength: Int, polynomialOrder: Int, derivativeOrder: Int = 0, delta: Int = 1) -> [Double] {
let (halfWindow, remainder) = windowLength.quotientAndRemainder(dividingBy: 2)
var pos = Double(halfWindow)
if remainder == 0 {
pos -= 0.5
}
let X = [Double](stride(from: Double(windowLength) - pos - 1, through: -pos, by: -1))
let P = [Double](stride(from: 0, through: Double(polynomialOrder), by: 1))
let A = P.map { exponent in
X.map {
pow($0, exponent)
}
}
var B = [Double](repeating: 0, count: polynomialOrder + 1)
B[derivativeOrder] = Double(factorial(derivativeOrder)) / pow(Double(delta), Double(derivativeOrder))
return leastSquaresSolution(A: A, B: B)
}
static func leastSquaresSolution(A: [[Double]], B: [Double]) -> [Double] {
let sparseA = A.sparseMatrix()
var sparseAValuesCopy = sparseA.values
var xValues = [Double](repeating: 0, count: A.transpose().count)
var bValues = B
sparseAValuesCopy.withUnsafeMutableBufferPointer { valuesPtr in
let a = SparseMatrix_Double(
structure: sparseA.structure,
data: valuesPtr.baseAddress!
)
bValues.withUnsafeMutableBufferPointer { bPtr in
xValues.withUnsafeMutableBufferPointer { xPtr in
let b = DenseVector_Double(
count: Int32(B.count),
data: bPtr.baseAddress!
)
let x = DenseVector_Double(
count: Int32(A.transpose().count),
data: xPtr.baseAddress!
)
#warning("EXC_BAD_ACCESS is thrown below")
print("This code is executed...")
let status = SparseSolve(SparseLSMR(), a, b, x, SparsePreconditionerDiagScaling)
print("...but, if an EXC_BAD_ACCESS is thrown, this code isn't")
if status != SparseIterativeConverged {
fatalError("Failed to converge. Returned with error \(status).")
}
}
}
}
return xValues
}
}
func factorial(_ n: Int) -> Int {
n < 2 ? 1 : n * factorial(n - 1)
}
extension Array where Element == [Double] {
func sparseMatrix() -> (structure: SparseMatrixStructure, values: [Double]) {
let columns = self.transpose()
var rowIndices: [Int32] = columns.map { column in
column.indices.compactMap { indexInColumn in
if column[indexInColumn] != 0 {
return Int32(indexInColumn)
}
return nil
}
}.reduce([], +)
let sparseColumns = columns.map { column in
column.compactMap {
if $0 != 0 {
return $0
}
return nil
}
}
var counter = 0
var columnStarts = [Int]()
for sparseColumn in sparseColumns {
columnStarts.append(counter)
counter += sparseColumn.count
}
let reducedSparseColumns = sparseColumns.reduce([], +)
columnStarts.append(reducedSparseColumns.count)
let structure: SparseMatrixStructure = rowIndices.withUnsafeMutableBufferPointer { rowIndicesPtr in
columnStarts.withUnsafeMutableBufferPointer { columnStartsPtr in
let attributes = SparseAttributes_t()
return SparseMatrixStructure(
rowCount: Int32(self.count),
columnCount: Int32(columns.count),
columnStarts: columnStartsPtr.baseAddress!,
rowIndices: rowIndicesPtr.baseAddress!,
attributes: attributes,
blockSize: 1
)
}
}
return (structure, reducedSparseColumns)
}
func transpose() -> Self {
let columns = self.count
let rows = self.reduce(0) { Swift.max($0, $1.count) }
return (0 ..< rows).reduce(into: []) { result, row in
result.append((0 ..< columns).reduce(into: []) { result, column in
result.append(row < self[column].count ? self[column][row] : 0)
})
}
}
}
I'm working on Swift 6 concurrency support for our app.
I've always thought of NSAccessibilityElement as being like all of the other UI classes- only used (or usable) on the main thread. As far as I've seen, they are always called on the main thread.
But in Xcode 16 beta 2, it's only marked as Sendable but not MainActor.
Is that just an oversight or do we need to worry about these being used / called on threads?
It's easy enough to do the async work (well, not that easy), but I don't want to do all that work if Xcode 16 beta 3 is just going to add a MainActor to it. I've already been burned by that once, in WebKit- the first beta was missing several MainActor declarations, in places where it was unclear from the documentation.
I added a bunch of async fixes to my delegates, only to have to take it all out when the second Xcode beta shipped and the SDK headers changed.
How complete are the async declarations in the Xcode 16 SDKs?
Hello,
I want to use Automatic Grammar Agreement to localise a string in my app, let say "three remaining activities". The string "three" is obtained by using a NumberFormatter with a numberStyle set to .spellOut (so I'm not using an Integer)
var formatter: NumberFormatter = NumberFormatter()
formatter.numberStyle = .spellOut
let formattedCount: String = numberFormatter.string(from: count as NSNumber)!
Text("key_with_string_\(formattedCount)")
In my string catalog, I have translated the key key_with_string_%@ like this ^[%@ remaining activity](inflect: true), but it does not work.
I've tried to add the integer value used by the number formatter in the key key_with_string_%@_%lld but it does not work.
Should Automatic Grammar Agreement work normally just by using the formatted string provided by the NumberFormatter?
If not, is there a way to specify to use a secondary variable (my count integer) to switch between different categories like one and other automatically?
Thanks !
Axel
I have a Matrix structure as defined below for working with 2D numerical data in Accelerate. The underlying numerical data in this Matrix struct is stored as an Array.
struct Matrix<T> {
let rows: Int
let columns: Int
var data: [T]
init(rows: Int, columns: Int, fill: T) {
self.rows = rows
self.columns = columns
self.data = Array(repeating: fill, count: rows * columns)
}
init(rows: Int, columns: Int, source: (inout UnsafeMutableBufferPointer<T>) -> Void) {
self.rows = rows
self.columns = columns
self.data = Array(unsafeUninitializedCapacity: rows * columns) { buffer, initializedCount in
source(&buffer)
initializedCount = rows * columns
}
}
subscript(row: Int, column: Int) -> T {
get { return self.data[(row * self.columns) + column] }
set { self.data[(row * self.columns) + column] = newValue }
}
}
Multiplication is implemented by the functions shown below.
import Accelerate
infix operator .*
func .* (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> {
precondition(lhs.rows == rhs.rows && lhs.columns == rhs.columns, "Matrices must have same dimensions")
let result = Matrix<Double>(rows: lhs.rows, columns: rhs.columns) { buffer in
vDSP.multiply(lhs.data, rhs.data, result: &buffer)
}
return result
}
func * (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> {
precondition(lhs.columns == rhs.rows, "Number of columns in left matrix must equal number of rows in right matrix")
var a = lhs.data
var b = rhs.data
let m = lhs.rows // number of rows in matrices A and C
let n = rhs.columns // number of columns in matrices B and C
let k = lhs.columns // number of columns in matrix A; number of rows in matrix B
let alpha = 1.0
let beta = 0.0
// matrix multiplication where C ← αAB + βC
let c = Matrix<Double>(rows: lhs.rows, columns: rhs.columns) { buffer in
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, &a, k, &b, n, beta, buffer.baseAddress, n)
}
return c
}
I can also define a Matrix structure where the underlying data is an UnsafeMutableBufferPointer. The buffer is handled by the MatrixData class.
struct Matrix<T> {
let rows: Int
let columns: Int
var data: MatrixData<T>
init(rows: Int, columns: Int, fill: T) {
self.rows = rows
self.columns = columns
self.data = MatrixData(count: rows * columns, fill: fill)
}
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
self.data = MatrixData(count: rows * columns)
}
subscript(row: Int, column: Int) -> T {
get { return self.data.buffer[(row * self.columns) + column] }
set { self.data.buffer[(row * self.columns) + column] = newValue }
}
}
class MatrixData<T> {
var buffer: UnsafeMutableBufferPointer<T>
var baseAddress: UnsafeMutablePointer<T> {
get { self.buffer.baseAddress! }
}
init(count: Int, fill: T) {
let start = UnsafeMutablePointer<T>.allocate(capacity: count)
self.buffer = UnsafeMutableBufferPointer(start: start, count: count)
self.buffer.initialize(repeating: fill)
}
init(count: Int) {
let start = UnsafeMutablePointer<T>.allocate(capacity: count)
self.buffer = UnsafeMutableBufferPointer(start: start, count: count)
}
deinit {
self.buffer.deinitialize()
self.buffer.deallocate()
}
}
Multiplication for this approach is implemented by the functions shown here.
import Accelerate
infix operator .*
func .* (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> {
precondition(lhs.rows == rhs.rows && lhs.columns == rhs.columns, "Matrices must have same dimensions")
let result = Matrix<Double>(rows: lhs.rows, columns: lhs.columns)
vDSP.multiply(lhs.data.buffer, rhs.data.buffer, result: &result.data.buffer)
return result
}
func * (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> {
precondition(lhs.columns == rhs.rows, "Number of columns in left matrix must equal number of rows in right matrix")
let a = lhs.data.baseAddress
let b = rhs.data.baseAddress
let m = lhs.rows // number of rows in matrices A and C
let n = rhs.columns // number of columns in matrices B and C
let k = lhs.columns // number of columns in matrix A; number of rows in matrix B
let alpha = 1.0
let beta = 0.0
// matrix multiplication where C ← αAB + βC
let c = Matrix<Double>(rows: lhs.rows, columns: rhs.columns)
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, a, k, b, n, beta, c.data.baseAddress, n)
return c
}
Both of these approaches give me similar performance. The only difference that I have noticed is the matrix buffer approach allows for reference semantics. For example, the code below uses half the memory with the matrix buffer approach compared to the matrix array approach. This is because b acts as a reference to a using the matrix buffer approach; otherwise, the matrix array approach makes a full copy of a.
let n = 10_000
let a = Matrix<Double>(rows: n, columns: n, fill: 0)
var b = a
b[0, 0] = 99
b[0, 1] = 22
Other than reference semantics, are there any reasons to use one of these approaches over the other?
Hello All, some background information first. I have the following struct:
Struct Category: Identifiable, Codeable, Hashable {
var id: UUID
var name: String
var subCategory: [Category]?
}
var categories: [Category]
There is no limit how many levels deep the subcategory can be. The user is essentially creating a hierarchical data filing system.
Given that the number of subCategory levels is unlimited, I am recursing over the subcategories to find the correct level at which to insert the newCategory.
The recursive function to add category is declared as:
func recursiveAddCategory(newCategory: Category, subCategoryOf: inout [Category]?)
you will note that I am trying to pass the subCategory as a reference (using inout), so that I can add to the original
and the function is called as recursiveAddCategory(newCategory, &categories.subCategory!)
the actual append statement within the recursiveAddCategory function is:
categories.subCategory?.append(newCategory)
I am encountering no errors but also find that the newCategory is not being added to the categories array.
Any help or guidance appreciated.
Thanks
I am working thru the issues of turning on Strict Concurrency Checking. I have a SwiftData application, and I am compressing images before saving them as data. My save function is pretty simple
private func save() {
ImageCompressor.compress(image: (frontImageSelected?.asUIImage())!, maxByte: 1_048_576) { image in
guard image != nil else {
print("Error compressing image")
return
}
if let greetingCard {
greetingCard.cardName = cardName
greetingCard.cardFront = image?.pngData()
greetingCard.cardManufacturer = cardManufacturer
greetingCard.cardURL = cardURL
greetingCard.eventType = eventType
} else {
let newGreetingCard = GreetingCard(cardName: cardName, cardFront: image?.pngData(), eventType: eventType, cardManufacturer: cardManufacturer, cardURL: cardURL)
modelContext.insert(newGreetingCard)
}
}
}
I compress the selected image, I had to change my ImageCompressor.compress closure to Sendable, but now every assignment above is flagging with the above warning. I define the greetingCard as var greetingCard: GreetingCard? in my view, since I can have it passed in for edit, or generated if new.
I also get the same warning on modelContext, which is defined as @Environment(\.modelContext) private var modelContext.
It's not clear to me how to address this warning. Any pointers would be helpful.
Sorry this post is duplicate
I have the following var in an @Observable class:
var displayResult: String {
if let currentResult = currentResult, let decimalResult = Decimal(string: currentResult) {
let result = decimalResult.formatForDisplay()
UIAccessibility.post(notification: .announcement, argument: "Current result \(result)")
return result
} else {
return "0"
}
}
The UIAccessiblity.post gives me this warning:
Reference to static property 'announcement' is not concurrency-safe because it involves shared mutable state; this is an error in Swift 6
How can I avoid this?
import Foundation
let formatter = DateFormatter()
let displayLocalFormat = true or false
let timeZone = UTC
let dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
let currentDate = Date()
formatter.locale = displayLocalFormat ? Locale.current : Locale(identifier: "en_US_POSIX")
formatter.dateFormat = dateFormat
formatter.timeZone = timeZone
formatter.string(from: date) // This function returns date format 2024-05-23T11:16:24.706 a.m.Z
struct Preview: View {
private static let NAME = "Test"
@Query(filter: #Predicate<Item> { $0.name == Preview.NAME})
private var items: [Item]
var body: some View {
MyView(name: Preview.NAME, items: items)
}
}
Compile error occurs: key path cannot refer to static member 'NAME'
How can a (static) constant be referred in member closure?
Hi,
When using Swift Concurrency blocking tasks like file I/O, GPU work and networking can prevent forward moving progress and have the potential to exhaust the cooperative thread pool and under utilize the CPU. It's been recommended to offload these tasks from the cooperative thread pool.
Is my understanding correct that the preferred way to do this is by creating async tasks via Dispatch or OperationQueue? And combining these with Continuations if a return value from the task is required? Or should I always be using Continuations in combination with Dispatch/OperationQueue?
There are also Executors but the documentation seems a bit limited on how to use these. The new TaskExecutor is also only available on the latest beta's.
My question is basically what is the recommend way to offload a task?
Thanks!
In my method moveSun() it successfully rotates and plays the sound the first time it is called. However, subsequent calls to the method only play the sound and do not execute the rotate action. Does anyone know what may be causing this? Here's the relevant code:
func moveSun()
{
print(sunMoving)
let rotateAction = SKAction.rotate(toAngle: 2 * CGFloat.pi, duration: 2)
let playGearSound = SKAction.playSoundFileNamed("spinningGear", waitForCompletion: true)
let rotateAndPlayGearSound = SKAction.group([rotateAction, playGearSound])
sun.run(rotateAndPlayGearSound, completion: { self.sunMoving = false; print("completed completion handler") })
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
for t in touches
{
self.touchDown(atPoint: t.location(in: self))
}
}
func touchDown(atPoint pos : CGPoint)
{
let touchedNodes = nodes(at: pos)
for touchedNode in touchedNodes
{
print("touchNode: \(String(describing: touchedNode.name))")
if touchedNode.name == "sun" && !sunMoving
{
sunMoving = true
moveSun()
}
}
}
I'm trying to migrate my fairly large application to Swift Concurrency. I've have a class marked as @MainActor that sub-classes a 3rd party abstract class that is not migrated to Swift Concurrency.
I get the following error:
Main actor-isolated class 'MyClass' has different actor isolation from nonisolated superclass 'OtherAbstractClass'; this is an error in the Swift 6 language mode
My class needs to be MainActor as it uses other code that is required to be on the MainActor.
I can't see how to suppress this warning, I know as a guarantee that the abstract class will always be on the main thread so I need a way of telling the compiler that when I don't own the 3rd party code.
import OtherAbstractModule
@MainActor
class MyClass: OtherAbstractClass {
....
}
How can I satisfy the compiler in this case?
Currently Swift Testing has much less features than XCTest, so the adoption will be very slow from our side. Notable features we miss are UI tests, performance tests and attachments.
I did not want to create many issues in Swift Testing GitHub project as lots of these shortcoming are most probably tracked internally (I can see lots of references to radars in GitHub issues.)
So, my question is: Is it a good idea to wait with wider adoption or should we experiment with other tools like swift Benchmarks?