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?
Post
Replies
Boosts
Views
Activity
Hello!
In our codebase we have a NSView subclass that conforms to NSTextInputClient. This protocol is currently not marked as a main actor, but in the decade this has been in use here it has always been called on the main thread from AppKit.
With Swift 6 (or complete concurrency checking in Swift 5) this conformance causes issues since NSView is a main actor but not this protocol. I've tried a few of the usual fixes (MainActor.assumeIsolated or prefixing the protocol conformance with @preconcurrency) but they were not able to resolve all warnings.
So I dug in the AppKit headers and found that NSTextInputClient is usually implemented by the view itself, but that that is not a hard requirement (see NSTextInputContext.h the documentation for the client property or here). With that I turned my NSView subclass extension into a separate class that is not a main actor and in my NSView subclass create an instance of it and NSTextInputContext. This all seems to work fine in my initial tests, the delegate methods are called. But when the window loses and then regains key, I see a warning message in the console output.
-[TUINSCursorUIController activate:]: Foo.TextInputClient isn't subclass of NSView.
So my question is, am I doing it wrong with the custom class that implements the protocol? Or is the warning wrong?
I would also appreciate a hint on how to better resolve the concurrency issues with NSTextInputClient. Is a main actor annotation coming at some point from your end?
Thanks!
Markus
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?
Before anyone rants and raves about checking documentation - I have spent the last 4 hours trying to solve this issue on my own before asking for help. Coding in Swift is VERY new for me and I'm banging my head against the wall trying to teach myself. I am very humbly asking for help. If you refer me to documentation, that's fine but I need examples or it's going to go right over my head. Teaching myself is hard, please don't make it more difficult.
I have ONE swift file with everything in it.
import Foundation
import Cocoa
import Observation
class GlobalString: ObservableObject {
@Published var apiKey = ""
@Published var link = ""
}
struct ContentView: View {
@EnvironmentObject var globalString: GlobalString
var body: some View {
Form {
Section(header: Text("WallTaker for macOS").font(.title)) {
TextField(
"Link ID:",
text: $globalString.link
)
.disableAutocorrection(true)
TextField(
"API Key:",
text: $globalString.apiKey
)
.disableAutocorrection(true)
Button("Take My Wallpaper!") {
}
}
.padding()
}
.task {
await Wallpaper().fetchLink()
}
}
}
@main
struct WallTaker_for_macOSApp: App {
@AppStorage("showMenuBarExtra") private var showMenuBarExtra = true
@EnvironmentObject var globalString: GlobalString
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(GlobalString())
}
// MenuBarExtra("WallTaker for macOS", systemImage: "WarrenHead.png", isInserted: $showMenuBarExtra) {
// Button("Refresh") {
//// currentNumber = "1"
// }
// Button("Love It!") {
//// currentNumber = "2"
// }
// Button("Hate It!") {
//// currentNumber = "3"
// }
// Button("EXPLOSION!") {
// // currentNumber = "3"
// }
////
// }
}
}
class Wallpaper {
var url: URL? = nil
var lastPostUrl: URL? = nil
let mainMonitor: NSScreen
init() {
mainMonitor = NSScreen.main!
}
struct LinkResponse: Codable {
var post_url: String?
var set_by: String?
var updated_at: String
}
struct Link {
var postUrl: URL?
var setBy: String
var updatedAt: Date
}
func parseIsoDate(timestamp: String) -> Date? {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
return formatter.date(from: timestamp)
}
func fetchLink() async {
do {
url = URL(string: GlobalString().link)
let (data, _) = try await URLSession.shared.data(from: url!)
let decoder = JSONDecoder()
let linkResponse = try decoder.decode(LinkResponse.self, from: data)
let postUrl: URL? = linkResponse.post_url != nil ? URL(string: linkResponse.post_url!) : nil
let date = parseIsoDate(timestamp: linkResponse.updated_at)
let link = Link(
postUrl: postUrl,
setBy: linkResponse.set_by ?? "anon",
updatedAt: date ?? Date()
)
try update(link: link)
} catch {
}
}
func update(link: Link) throws {
guard let newPostUrl = link.postUrl else {
return
}
if (newPostUrl != lastPostUrl) {
lastPostUrl = newPostUrl
let tempFilePath = try getTempFilePath()
try downloadImageTo(sourceURL: newPostUrl, destinationURL: tempFilePath)
try applyWallpaper(url: tempFilePath)
} else {
}
}
private func applyWallpaper(url: URL) throws {
try NSWorkspace.shared.setDesktopImageURL(url, for: mainMonitor, options: [:])
}
private func getTempFilePath() throws -> URL {
let directory = NSTemporaryDirectory()
let fileName = NSUUID().uuidString
let fullURL = NSURL.fileURL(withPathComponents: [directory, fileName])!
return fullURL
}
private func downloadImageTo(sourceURL: URL, destinationURL: URL) throws {
let data = try Data(contentsOf: sourceURL)
try data.write(to: destinationURL)
}
}
The 'fetchLink' function is where things explode, specifically when setting the URL. I do not know what I'm doing wrong.
I have a public swift function with the below declaration :
public func InternalMain (_ pNumOfArgs : Int32, _ pCmdlineArgs : UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>) -> Int32 {..}
I need this function as public because I need to invoke in from a different library. But the above declaration produces an error in my generated swift header i.e '-swift.h' file because 'UnsafeMutablePointer<UnsafeMutablePointer?>' type cannot be represented in the swift generated header.
Can someone help how do I get past this. This is a class independent function and I tried using the '@nonobj' to prevent this from getting in the generated header but it still gives an error.
Hello,
I develop an HCE payment app.
In this app I can redirect users in Settings to set the default payment app
UIApplication.shared.open(URL(string: "App-prefs:General&path=CONTACTLESS_NFC")
But is it possible to know which app is selected or if my app is already set as default ?
Why is "Go small with embedded Swift" still not available, despite the fact all the other WWDC24 Tuesday session videos are?
Hello, I'm using the generator to create a client from this API:
https://github.com/griptape-ai/griptape-cloud-control-plane/blob/main/models/Griptape.openapi.json
Everything seems fine until I go to call a method. I get an error on a DateTime format mismatch in the response.
Client error - cause description: 'Unknown', underlying error: DecodingError: dataCorrupted - at : Expected date string to be ISO8601-formatted. (underlying error: <nil>),
Is there a decoder option or something I can attach to the generated client code to adjust for this?
Since I start to wrote UITest, this keep happened with no waring, following image
is the log, sensitive info has been replaced.
However, once I run app, then run test again, UITest just work out, it seems like a wired but, and the method just a working around bug to me,
When we pass some special words, NSString.getBytes does not crash even when we pass an invalid range.
It seems a bug.
The below code is an example.
func testNSStringGetBytes() {
let originalString: String = "あ"
let bufferSize = 256
var buffer = [UInt8](repeating: 0, count: bufferSize)
var usedLength = 0
// An invalid range is passed
let range = NSRange(location: 0, length: originalString.count + 1)
var remainingRange = NSRange()
(originalString as NSString)
.getBytes(
&buffer,
maxLength: bufferSize,
usedLength: &usedLength,
encoding: String.Encoding.utf8.rawValue,
options: [],
range: range,
remaining: &remainingRange
)
print("Used Length: \(usedLength)")
print("Buffer: \(buffer[0..<usedLength])")
if remainingRange.length > 0 {
print("Did not convert the whole string. Remaining range: \(remainingRange)")
} else {
print("Entire string was converted successfully.")
}
}
I'm building a macOS target for my App (which also has some Obj-C code).
Building and running the app is fine but when I archive the app in XCode, the process / build fails with the following error
Type 'BOOL' (aka ;Int32') cannot be used as a boolean;test for '!=0' instead
It happens in a couple of places, one of the places being
private func getRootDirectory(createIfNotExists: Bool = true) throws -> URL {
return try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
}
where it complains that create: true is not acceptable and throws the above error.
If I comment out this line, the archive works successfully.
When i Cmd + click the definition of Filemanager.default.url , i get this
@available(macOS 10.6, *)
open func url(for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, appropriateFor url: URL?, create shouldCreate: BOOL) throws -> URL
This looks fishy since it it says create shouldCreate: BOOL whereas the documentation says it should be just Bool
func url(
for directory: FileManager.SearchPathDirectory,
in domain: FileManager.SearchPathDomainMask,
appropriateFor url: URL?,
create shouldCreate: Bool
) throws -> URL
My minimum deployment target is macOS 13.0
I'm quite stumped at this error - which happens only while archiving. Does anybody know why?