I have developed a sample app following the example found Updating your app package installer to use the new Service Management API and referring this discussion on XPC Security.
The app is working fine, I have used Swift NSXPCConnection in favour of xpc_connection_create_mach_service used in the example. (I am running app directly from Xcode)
I am trying to set up security requirements for the client connection using setCodeSigningRequirement on the connection instance.
But it fails for even basic requirement connection.setCodeSigningRequirement("anchor apple").
Error is as follows.
cannot open file at line 46986 of [554764a6e7]
os_unix.c:46986: (0) open(/private/var/db/DetachedSignatures) - Undefined error: 0
xpc_support_check_token: anchor apple error: Error Domain=NSOSStatusErrorDomain Code=-67050 "(null)" status: -67050
I have used codesign -d --verbose=4 /path/to/executable to check the attributes I do get them in the terminal.
Other way round, I have tried XPC service provider sending back process id (pid) with each request, and I am probing this id to get attributes using this code which gives all the details.
func inspectCodeSignature(ofPIDString pidString: String) {
guard let pid = pid_t(pidString) else {
print("Invalid PID string: \(pidString)")
return
}
let attributes = [kSecGuestAttributePid: pid] as CFDictionary
var codeRef: SecCode?
let status = SecCodeCopyGuestWithAttributes(nil, attributes, [], &codeRef)
guard status == errSecSuccess, let code = codeRef else {
print("Failed to get SecCode for PID \(pid) (status: \(status))")
return
}
var staticCode: SecStaticCode?
let staticStatus = SecCodeCopyStaticCode(code, [], &staticCode)
guard staticStatus == errSecSuccess, let staticCodeRef = staticCode else {
print("Failed to get SecStaticCode (status: \(staticStatus))")
return
}
var infoDict: CFDictionary?
if SecCodeCopySigningInformation(staticCodeRef, SecCSFlags(rawValue: kSecCSSigningInformation), &infoDict) == errSecSuccess,
let info = infoDict as? [String: Any] {
print("🔍 Code Signing Info for PID \(pid):")
print("• Identifier: \(info["identifier"] ?? "N/A")")
print("• Team ID: \(info["teamid"] ?? "N/A")")
if let entitlements = info["entitlements-dict"] as? [String: Any] {
print("• Entitlements:")
for (key, value) in entitlements {
print(" - \(key): \(value)")
}
}
} else {
print("Failed to retrieve signing information.")
}
var requirement: SecRequirement?
if SecRequirementCreateWithString("anchor apple" as CFString, [], &requirement) == errSecSuccess,
let req = requirement {
let result = SecStaticCodeCheckValidity(staticCodeRef, [], req)
if result == errSecSuccess {
print("Signature is trusted (anchor apple)")
} else {
print("Signature is NOT trusted by Apple (failed anchor check)")
}
}
var infoDict1: CFDictionary?
let signingStatus = SecCodeCopySigningInformation(staticCodeRef, SecCSFlags(rawValue: kSecCSSigningInformation), &infoDict1)
guard signingStatus == errSecSuccess, let info = infoDict1 as? [String: Any] else {
print("Failed to retrieve signing information.")
return
}
print("🔍 Signing Info for PID \(pid):")
for (key, value) in info.sorted(by: { $0.key < $1.key }) {
print("• \(key): \(value)")
}
}
If connection.setCodeSigningRequirement does not works I plan to use above logic as backup.
Q: Please advise is there some setting required to be enabled or I have to sign code with some flags enabled.
Note: My app is not running in a Sandbox or Hardened Runtime, which I want.
Swift
RSS for tagSwift is a powerful and intuitive programming language for Apple platforms and beyond.
Posts under Swift tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
How do I filter data using @Query with a Set of DateComponents? I successfully saved multiple dates using a MultiDatePicker in AddView.swift. In ListView.swift, I want to retrieve all records for the current or today’s date.
There are hundreds of examples using @Query with strings and dates, but I haven’t found an example of @Query using a Set of DateComponents
Nothing will compile and after hundreds and hundreds of attempts, my hair is turning gray.
Please, please, please help me.
For example, if the current date is Tuesday, March 4 205, then I want to retrieve both records. Since both records contain Tuesday, March 4, then retrieve both records. Sorting works fine because the order by clause uses period which is a Double.
Unfortunately, my syntax is incorrect and I don’t know the correct predicate syntax for @Query and a Set of DateComponents.
Class Planner.swift file
import SwiftUI
import SwiftData
@Model
class Planner {
//var id: UUID = UUID()
var grade: Double = 4.0
var kumi: Double = 4.0
var period: Double = 1.0
var dates: Set<DateComponents> = []
init(
grade: Double = 4.0, kumi: Double = 4.0, period: Double = 1.0, dates: Set<DateComponents> = []
)
{
self.grade = grade
self.kumi = kumi
self.period = period
self.dates = dates
}
}
@Query Model snippet of code does not work
The compile error is to use a Set of DateComponents, not just DateComponents.
@Query(filter: #Predicate<Planner> { $0.dates = DateComponents(calendar: Calendar.current, year: 2025, month: 3, day: 4)},
sort: [SortDescriptor(\Planner.period)])
var planner: [Planner]
ListView.swift image
EditView.swift for record #1
DB Browser for SQLlite: record #1 (March 6, 2025 and March 4, 2025)
[{"isLeapMonth":false,"year":2025,"day":6,"month":3,"calendar":{"identifier":"gregorian","minimumDaysInFirstWeek":1,"current":1,"locale":{"identifier":"en_JP","current":1},"firstWeekday":1,"timeZone":{"identifier":"Asia\/Tokyo"}},"era":1},{"month":3,"year":2025,"day":4,"isLeapMonth":false,"era":1,"calendar":{"locale":{"identifier":"en_JP","current":1},"timeZone":{"identifier":"Asia\/Tokyo"},"current":1,"identifier":"gregorian","firstWeekday":1,"minimumDaysInFirstWeek":1}}]
EditView.swift for record #2
DB Browser for SQLlite: record #2 (March 3, 2025 and March 4, 2025)
[{"calendar":{"minimumDaysInFirstWeek":1,"locale":{"current":1,"identifier":"en_JP"},"timeZone":{"identifier":"Asia\/Tokyo"},"firstWeekday":1,"current":1,"identifier":"gregorian"},"month":3,"day":3,"isLeapMonth":false,"year":2025,"era":1},{"year":2025,"month":3,"era":1,"day":4,"isLeapMonth":false,"calendar":{"identifier":"gregorian","current":1,"firstWeekday":1,"minimumDaysInFirstWeek":1,"timeZone":{"identifier":"Asia\/Tokyo"},"locale":{"current":1,"identifier":"en_JP"}}}]
Any help is greatly appreciated.
In an under-development MacOS & iOS app, I need to identify various measurements from OCR'ed text: length, weight, counts per inch, area, percentage. The unit type (e.g. UnitLength) needs to be identified as well as the measurement's unit (e.g. .inches) in order to convert the measurement to the app's internal standard (e.g. centimetres), the value of which is stored the relevant CoreData entity.
The use of NLTagger and NLTokenizer is problematic because of the various representations of the measurements: e.g. "50g.", "50 g", "50 grams", "1 3/4 oz."
Currently, I use a bespoke algorithm based on String contains and step-wise evaluation of characters, which is reasonably accurate but requires frequent updating as further representations are detected.
I'm aware of the Python SpaCy model being capable of NER Measurement recognition, but am reluctant to incorporate a Python-based solution into a production app. (ref [https://developer.apple.com/forums/thread/30092])
My preference is for an open-source NER Measurement model that can be used as, or converted to, some form of a Swift compatible Machine Learning model. Does anyone know of such a model?
When an external keyboard is connected to the iPad, the software keyboard often becomes hidden and cannot be made to show again programmatically.
Help! Is there a way to programmatically get the software keyboard to re-appear when an external keyboard is connected without clicking 'Show Keyboard' from the Keyboard Shortcuts menu-item button?
Its corner-casey for sure, (with our own keyboard extension) we have a sub-view that is added to the software keyboard view under a certain use case. When the user has an external keyboard connected, everything is fine until the app is backgrounded. When the app is re-foregrounded the software keyboard often becomes hidden (what the user now sees is a keyboard shortcut menu-item group w/a keyboard button and a mic button.) This makes it impossible for the user to interact with the subview we added (because it is hidden), unless the user manually shows the software keyboard again by clicking "Show Keyboard" from the keyboard shortcut.
The software keyboard view is still the 'firstResponder' (accepting key strokes, etc), we just cannot find a way to programmatically make it visible again. Sigh.
I ran into a problem. When using Storekit1 to purchase an SKU, the user payment was successful, but StoreKit1 did return paymentCancelled to my App. I would like to know under what circumstances this problem may occur? How do I fix it? Thank you
Hello, I have to create an app in Swift that it scan NFC Identity card. It extract data and convert it to human readable data. I do it with below code
import CoreNFC
class NFCIdentityCardReader: NSObject , NFCTagReaderSessionDelegate {
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
print("\(session.description)")
}
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: any Error) {
print("NFC Error: \(error.localizedDescription)")
}
var session: NFCTagReaderSession?
func beginScanning() {
guard NFCTagReaderSession.readingAvailable else {
print("NFC is not supported on this device")
return
}
session = NFCTagReaderSession(pollingOption: .iso14443, delegate: self, queue: nil)
session?.alertMessage = "Hold your NFC identity card near the device."
session?.begin()
}
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
guard let tag = tags.first else {
session.invalidate(errorMessage: "No tag detected")
return
}
session.connect(to: tag) { (error) in
if let error = error {
session.invalidate(errorMessage: "Connection error: \(error.localizedDescription)")
return
}
switch tag {
case .miFare(let miFareTag):
self.readMiFareTag(miFareTag, session: session)
case .iso7816(let iso7816Tag):
self.readISO7816Tag(iso7816Tag, session: session)
case .iso15693, .feliCa:
session.invalidate(errorMessage: "Unsupported tag type")
@unknown default:
session.invalidate(errorMessage: "Unknown tag type")
}
}
}
private func readMiFareTag(_ tag: NFCMiFareTag, session: NFCTagReaderSession) {
// Read from MiFare card, assuming it's formatted as an identity card
let command: [UInt8] = [0x30, 0x04] // Example: Read command for block 4
let requestData = Data(command)
tag.sendMiFareCommand(commandPacket: requestData) { (response, error) in
if let error = error {
session.invalidate(errorMessage: "Error reading MiFare: \(error.localizedDescription)")
return
}
let readableData = String(data: response, encoding: .utf8) ?? response.map { String(format: "%02X", $0) }.joined()
session.alertMessage = "ID Card Data: \(readableData)"
session.invalidate()
}
}
private func readISO7816Tag(_ tag: NFCISO7816Tag, session: NFCTagReaderSession) {
let selectAppCommand = NFCISO7816APDU(instructionClass: 0x00, instructionCode: 0xA4, p1Parameter: 0x04, p2Parameter: 0x00, data: Data([0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01]), expectedResponseLength: -1)
tag.sendCommand(apdu: selectAppCommand) { (response, sw1, sw2, error) in
if let error = error {
session.invalidate(errorMessage: "Error reading ISO7816: \(error.localizedDescription)")
return
}
let readableData = response.map { String(format: "%02X", $0) }.joined()
session.alertMessage = "ID Card Data: \(readableData)"
session.invalidate()
}
}
}
But I got null. I think that these data are encrypted. How can I convert them to readable data without MRZ, is it possible ?
I need to get personal informations from Identity card via Core NFC.
Thanks in advance.
Best regards
I am trying to retrieve delivered notifications using UNUserNotificationCenter.getDeliveredNotifications(completionHandler:), but I have encountered an issue:
Notifications triggered by UNTimeIntervalNotificationTrigger or UNCalendarNotificationTrigger appear in the delivered list.
However, notifications triggered by UNLocationNotificationTrigger do not appear in the list.
Here is the code I use to fetch delivered notifications:
UNUserNotificationCenter.current().getDeliveredNotifications { notifications in
for notification in notifications {
print("Received notification: \(notification.request.identifier)")
}
}
The notification is scheduled as follows:
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Test Notification"
content.body = "This is a location-based notification."
content.sound = .default
let coordinate = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194) // Example coordinates
let region = CLCircularRegion(center: coordinate, radius: 100, identifier: "TestRegion")
region.notifyOnEntry = true
region.notifyOnExit = false
let trigger = UNLocationNotificationTrigger(region: region, repeats: false)
let request = UNNotificationRequest(identifier: "LocationTest", content: content, trigger: trigger)
center.add(request) { error in
if let error = error {
print("Error adding notification: \(error.localizedDescription)")
}
}
Why does getDeliveredNotifications not return notifications that were triggered using UNLocationNotificationTrigger?
How can I retrieve such notifications after they have been delivered?
As of iOS 18.3 SDK, Core Bluetooth is still mostly an Objective-C framework: key objects like CBPeripheral inherit from NSObjectProtocol and does not conform to Sendable.
CBCentralManager has a convenience initializer that allows the caller to provide a dispatch_queue for delegate callbacks. I want my Swift package that implements Core Bluetooth to conform to Swift 6 strict concurrency checking.
It is unsafe to dispatch the delegate events onto my own actor, as the passed in objects are presumably not thread-safe. What is the recommended concurrency safe way to implement Core Bluetooth in Swift 6 with strict concurrency checking enabled?
I am developing a sample authorization plugin to sync the user’s local password to the network password. During the process, I prompt the user to enter both their old and new passwords in custom plugin. After the user enters the information, I use the following code to sync the passwords:
try record.changePassword(oldPssword, toPassword: newPassword)
However, I have noticed that this is clearing all saved keychain information, such as web passwords and certificates. Is it expected behavior for record.changePassword to clear previously stored keychain data?
If so, how can I overcome this issue and ensure the keychain information is preserved while syncing the password?
Thank you for your help!
var format = "%7B%22sign%22%3Anull%2C%22company%22%3A%22%E5%85%84%E5%BC%9F%E6%B5%B7%E6%B4%8B%E7%A7%91%E6%8A%80%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8%22%2C%22businessNo%22%3Anull%2C%22scene%22%3Anull%2C%22interviewCode%22%3A%22767676%22%7D"
let message = withVaList([]) { args in
let msg = NSString(format: format, arguments: args)
print(msg)
}
Topic:
App & System Services
SubTopic:
General
Tags:
Foundation
iPad and iOS apps on visionOS
Swift
Debugging
I'm having an issue specifically with SwiftUI previews in my iOS project. The project builds and runs fine on devices and simulators (in Rosetta mode), but SwiftUI previews fail to load in both Rosetta and native arm64 simulator environments. The main error in the preview is related to the Alamofire dependency in my SiriKit Intents extension:
Module map file '[DerivedData path]/Build/Products/Debug-iphonesimulator/Alamofire/Alamofire.modulemap' not found
This error repeats for multiple Swift files within my SiriKit Intents extension. Additionally, I'm seeing:
Cannot load underlying module for 'Alamofire
Environment
Xcode version: 16.2
macOS version: Sonoma 14.7
Swift version: 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
Dependency management: CocoaPods
Alamofire version: 5.8
My project is a large, older codebase that contains a mix of UIKit, Objective-C and Swift
Architecture Issue: The project only builds successfully in Rosetta mode for simulators. SwiftUI previews are failing in both Rosetta and native arm64 environments. This suggests there may be a fundamental issue with how the preview system interacts with the project's architecture configuration. What I've Tried I've attempted several solutions without success:
Cleaning the build folder (⇧⌘K and Option+⇧⌘K)
Deleting derived data
Reinstalling dependencies
Restarting Xcode
Removing and re-adding Alamofire
Hi all. I need to save an array of strings in userdefaults. I am using
NSKeyedArchiver.archivedData(withRootObject: rootObject, requiringSecureCoding: false)
to convert array of string to data and then save it in userdefaults.
Inorder to retrieve the data back, I am using
let data = self.userDefaults.data(forKey: "key")!
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
unarchiver.requiresSecureCoding = false
let array = unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as? NSObject
This was working perfectly till iOS 18. From iOS 18 in couple of devices, we are getting empty string array while we retrieve the value back from userdefaults. We observed this in an iPhone 12 pro and iPhone 15 running on iOS 18. iPhone 12 pro is facing this issue almost once everyday. In iPhone 15 this happens once in 2-3 days.
Tried printing raw data directly from userdefaults. And I can see some data available. But when we convert that back to array of string, I am getting empty. Tried adding logs in catch block. But couldn't get any. What might be the cause of this issue?
It takes a few seconds, sometimes a few minutes for records to be downloaded back from CloudKit when the user reinstalls the app, which leads users to thinking their data was lost. I would like to know if there’s any way to provide a visual feedback about the current CloudKit sync status so I can let users know their data is being in fact downloaded back to their devices.
Hi,
I’m practicing with NavigationSplitView for macOS and customizing the sidebar. I’ve managed to adjust most parts, but I couldn’t remove the sidebar’s divider. It seems like it’s not possible in modern SwiftUI. My AppKit knowledge is also not very strong.
How can I remove the sidebar divider?
I want to use a plain background. I also solved it by creating my own sidebar, but I wanted to try it using NavigationSplitView.
I'm attempting to create a proof of concept of a static library, distributed as an XCFramework, which has two local XCFramework dependencies.
The reason for this is because I'm working to provide a single statically linked library to a customer, instead of providing them with the static library plus the two dependencies.
The Issue
With a fairly simple example project, I'm not able to access any code from the static library without the complier throwing a "No such module" error and saying that it cannot find one of the dependent modules.
Project Layout
I have an example project that has some example targets with basic example code.
Example Project on Github
Target: FrameworkA
Mach-0 Type: Dynamic
Build Mergable Library: Yes
Skip Install: No
Build Libraries For Distribution: Yes
Target: FrameworkB
Mach-0 Type: Dynamic
Build Mergable Library: Yes
Skip Install: No
Build Libraries For Distribution: Yes
XCFrameworks are being generated from these two targets using Apple's recommendations. I've verified that the mergable metadata is present in both framework's Info.plist files.
Each exposes a single struct which will return an example String.
Finally I have my SDK target:
Target: ExampleKit
Mach-0 Type: Static
Build Mergable Library: No
Create Merged Binary: Manual
Skip Install: No
Build Libraries For Distribution: Yes
The two .xcframework files are in the Target's folder structure as well. The "Link Binary With Libraries" build phase includes them and they're Required.
Inside of the ExampleKit target, I have a single public struct which has two static properties which return the example strings from FrameworkA and FrameworkB.
I then have another script which generates an XCFramework from this target.
Expectations
Based on Apple's documentation and the "Meet Mergable Libraries" WWDC session I would expect that I could make a simple iOS app, link the ExampleKit.xcframework, import ExampleKit inside of a file, and be able to access the single public struct present in ExampleKit. Unfortunately, all I get is "No such module FrameworkA".
I would expect that FrameworkA and FrameworkB would have been merged into ExampleKit? I'm really unsure of where to go from here in debugging this. And more importantly, is this even a possible thing to do?
I have an @objC used for notification.
kTag is an Int constant, fieldBeingEdited is an Int variable.
The following code fails at compilation with error: Command CompileSwift failed with a nonzero exit code if I capture self (I edited code, to have minimal case)
@objc func keyboardDone(_ sender : UIButton) {
DispatchQueue.main.async { [self] () -> Void in
switch fieldBeingEdited {
case kTag : break
default : break
}
}
}
If I explicitly use self, it compiles, even with self captured:
@objc func keyboardDone(_ sender : UIButton) {
DispatchQueue.main.async { [self] () -> Void in
switch fieldBeingEdited { // <<-- no need for self here
case self.kTag : break // <<-- self here
default : break
}
}
}
This compiles as well:
@objc func keyboardDone(_ sender : UIButton) {
DispatchQueue.main.async { () -> Void in
switch self.fieldBeingEdited { // <<-- no need for self here
case self.kTag : break // <<-- self here
default : break
}
}
}
Is it a compiler bug or am I missing something ?
Hi,
I have a file provider based MacOS application where i have a drive added and am trying to download a folder from that drive.
The folder has sub folders and large files in it.
After some time of download started, i keep getting below error.
error: ["The operation could not be completed. Cannot allocate memory", [code: 12, domain: "NSPOSIXErrorDomain"]
The download action is triggered via Finder's download icon(cloud icon with down arrow).
I am using native URLSession to download the files from server. No third party library is used.
What could be the possible reasons for "can not allocate memory" issue?
No real intruduction for this, so I'll get to the point:
All this code is on GitHub: https://github.com/the-trumpeter/Timetaber-for-iWatch
But first, sorry;
/*
I got roasted,
last time I posted;
for not defining my stuff.
This'll be different,
but's gonna be rough;
'cuz there's lots and lots
to get through:
*/
//this is 'Timetaber Watch App/Define (No expressions)/Courses_vDef.swift' on the GitHub:
struct Course {
let name: String
let icon: String
let room: String
let colour: String
let listName: String
let listIcon: String
let joke: String
init(name: String, icon: String, room: String? = nil, colour: String,
listName: String? = nil, listIcon: String? = nil, joke: String? = nil)
{
self.name = name
self.icon = icon
self.room = room ?? "None"
self.colour = colour
self.listName = listName ?? name
self.listIcon = listIcon ?? (icon+".circle.fill")
self.joke = joke ?? ""
}
}
//this is 'Timetaber Watch App/TimeManager_fDef.swift' on the GitHub:
func getCurrentClass(date: Date) -> Array<Course> {
//returns the course in session depending on the input date
//it is VERY long but
//all you really need to know is what it returns:
//basically: return [rightNow, nextUp]
}
/*
I thought that poetry
would be okay,
But poorly thought things through:
For I'll probably find
that people online
will treat my rhymes like spew.
*/
So into the question:
I have a bunch of views, all (intendedly) watching two variables inside of a class:
//Github: 'Timetaber Watch App/TimetaberApp.swift'
class GlobalData: ObservableObject {
@Published var currentCourse: Course = getCurrentClass(date: .now)[0] // the current timetabled class in session.
@Published var nextCourse: Course = getCurrentClass(date: .now)[1] // the next timetabled class in session
}
...and a bunch of views using them in different ways as follows:
(Sorry, don't have the characters to define functions called in these)
import SwiftUI
//Github: 'Timetaber Watch App/Views/HomeView.swift'
struct HomeView: View {
@StateObject var data = GlobalData()
var body: some View {
//HERE:
let icon = data.currentCourse.icon
let name = data.currentCourse.name
let colour = data.currentCourse.colour
let room = roomOrBlank(course: data.currentCourse)
let next = data.nextCourse
VStack {
//CURRENT CLASS
Image(systemName: icon)
.foregroundColor(Color(colour))//add an SF symbol element
.imageScale(.large)
.font(.system(size: 25).weight(.semibold))
Text(name)
.font(.system(size:23).weight(.bold))
.foregroundColor(Color(colour))
.padding(.bottom, 0.1)
//ROOM
Text(room+"\n")
.multilineTextAlignment(.center)
.foregroundStyle(.gray)
.font(.system(size: 15))
if next.name != noSchool.name {
Spacer()
//NEXT CLASS
Text(nextPrefix(course: next))
.font(.system(size: 15))
Text(getNextString(course: next))
.font(.system(size: 15))
.multilineTextAlignment(.center)
}
}.padding()
}
}
// Github: 'Timetaber Watch App/Views/ListView.swift'
struct listTemplate: View {
@StateObject var data = GlobalData()
var listedCourse: Course = failCourse(feedback: "lT.12")
var courseTime: String = ""
init(course: Course, courseTime: String) {
self.courseTime = courseTime
self.listedCourse = course
}
var body: some View {
let localroom = if listedCourse.room == "None" {
"" } else { listedCourse.room }
let image = if listedCourse.listIcon == "custom1" {
Image(.paintbrushPointedCircleFill)
} else { Image(systemName: listedCourse.listIcon) }
HStack{
image
.foregroundColor(Color(listedCourse.colour))
.padding(.leading, 5)
Text(listedCourse.name)
.bold()
Spacer()
Text(courseTime)
Text(localroom).bold().padding(.trailing, 5)
}
.padding(.bottom, 1)
.background(data.currentCourse.name==listedCourse.name ? Color(listedCourse.colour).colorInvert(): nil) //HERE
}
}
struct listedDay: View {
let day: Dictionary<Int, Course>
var body: some View {
let dayKeys = Array(day.keys).sorted(by: <)
List {
ForEach((0...dayKeys.count-2), id: \.self) {
let num = $0
listTemplate(course: day[dayKeys[num]] ?? failCourse(feedback: "lD.53"), courseTime: time24toNormal(time24: dayKeys[num]))
}
}
}
}
struct ListView: View {
var body: some View {
if storage.shared.termRunningGB && weekdayFunc(inDate: .now) != 1
&& weekdayFunc(inDate: .now) != 7 {
ScrollView {
listedDay(
day: getTimetableDay(
isWeekA:
getIfWeekIsA_FromDateAndGhost(
originDate: .now,
ghostWeek: storage.shared.ghostWeekGB
),
weekDay: weekdayFunc(inDate: .now)
)
)
}
} else if !storage.shared.termRunningGB {
Text("There's no term running.\nThe day's classes will be displayed here.")
.multilineTextAlignment(.center)
.foregroundStyle(.gray)
.font(.system(size: 13))
} else {
Text("No school today.\nThe day's classes will be displayed here.")
.multilineTextAlignment(.center)
.foregroundStyle(.gray)
.font(.system(size: 13))
}
}
}
//There's one more view but I can't fit it for characters.
//On GitHub: 'Timetaber Watch App/Views/SettingsView.swift'
So...
THE FUNCTION:
This function is called when changes are made that will affect the correct output of getCurrentClass. It is intended to reload the views and the current/next variables to reflect those changes.\
//GHub: 'Timetaber Watch App/StorageManager.swift'
func reload() -> Void {
@ObservedObject var globalData: GlobalData //this line is erroring, I don't know how to fix it. Is this even the best/proper way to do this?
let courseData = getCurrentClass(date: .now)
globalData.currentCourse = courseData[0]
globalData.nextCourse = courseData[1]
//Variable '_globalData' used by function definition before being initialized
//that is the error appearing on those above two redefinitions.
print("Setup done\n")
}
Thanks!
-Gill
This is an issue that occurred while using SwiftUI.
Cannot find '$state' in scope
The other view finds properties normally.
May I know why the error is occurring?
The following code is the full text of the code that causes problems.
import SwiftUI
@Observable
class HomeState {
var title: String = "Home"
}
struct HomeView: View {
@Binding var state: HomeState
var body: some View {
Text(state.title)
}
}
#Preview {
@Previewable @State var state: HomeState = .init()
HomeView(state: $state) /// Error: Cannot find '$state' in scope
}
The same error occurs when using the String type rather than the object.
What did I do wrong?
I’m trying to create a property wrapper that that can manage shared state across any context, which can get notified if changes happen from somewhere else.
I'm using mutex, and getting and setting values works great. However, I can't find a way to create an observer pattern that the property wrappers can use.
The problem is that I can’t trigger a notification from a different thread/context, and have that notification get called on the correct thread of the parent object that the property wrapper is used within.
I would like the property wrapper to work from anywhere: a SwiftUI view, an actor, or from a class that is created in the background. The notification preferably would get called synchronously if triggered from the same thread or actor, or otherwise asynchronously. I don’t have to worry about race conditions from the notification because the state only needs to reach eventuall consistency.
Here's the simplified pseudo code of what I'm trying to accomplish:
// A single source of truth storage container.
final class MemoryShared<Value>: Sendable {
let state = Mutex<Value>(0)
func withLock(_ action: (inout Value) -> Void) {
state.withLock(action)
notifyObservers()
}
func get() -> Value
func notifyObservers()
func addObserver()
}
// Some shared state used across the app
static let globalCount = MemoryShared<Int>(0)
// A property wrapper to access the shared state and receive changes
@propertyWrapper
struct SharedState<Value> {
public var wrappedValue: T {
get { state.get() }
nonmutating set { // Can't set directly }
}
var publisher: Publisher {}
init(state: MemoryShared) {
// ...
}
}
// I'd like to use it in multiple places:
@Observable
class MyObservable {
@SharedState(globalCount)
var count: Int
}
actor MyBackgroundActor {
@SharedState(globalCount)
var count: Int
}
@MainActor
struct MyView: View {
@SharedState(globalCount)
var count: Int
}
What I’ve Tried
All of the examples below are using the property wrapper within a @MainActor class. However the same issue happens no matter what context I use the wrapper in: The notification callback is never called on the context the property wrapper was created with.
I’ve tried using @isolated(any) to capture the context of the wrapper and save it to be called within the state in with unchecked sendable, which doesn’t work:
final class MemoryShared<Value: Sendable>: Sendable {
// Stores the callback for later.
public func subscribe(callback: @escaping @isolated(any) (Value) -> Void) -> Subscription
}
@propertyWrapper
struct SharedState<Value> {
init(state: MemoryShared<Value>) {
MainActor.assertIsolated() // Works!
state.subscribe {
MainActor.assertIsolated() // Fails
self.publisher.send()
}
}
}
I’ve tried capturing the isolation within a task with AsyncStream. This actually compiles with no sendable issues, but still fails:
@propertyWrapper
struct SharedState<Value> {
init(isolation: isolated (any Actor)? = #isolation, state: MemoryShared<Value>) {
let (taskStream, continuation) = AsyncStream<Value>.makeStream()
// The shared state sends new values to the continuation.
subscription = state.subscribe(continuation: continuation)
MainActor.assertIsolated() // Works!
let task = Task {
_ = isolation
for await value in taskStream {
_ = isolation
MainActor.assertIsolated() // Fails
}
}
}
}
I’ve tried using multiple combine subjects and publishers:
final class MemoryShared<Value: Sendable>: Sendable {
let subject: PassthroughSubject<T, Never> // ...
var publisher: Publisher {} // ...
}
@propertyWrapper
final class SharedState<Value> {
var localSubject: Subject
init(state: MemoryShared<Value>) {
MainActor.assertIsolated() // Works!
handle = localSubject.sink {
MainActor.assertIsolated() // Fails
}
stateHandle = state.publisher.subscribe(localSubject)
}
}
I’ve also tried:
Using NotificationCenter
Making the property wrapper a class
Using NSKeyValueObserving
Using a box class that is stored within the wrapper.
Using @_inheritActorContext.
All of these don’t work, because the event is never called from the thread the property wrapper resides in.
Is it possible at all to create an observation system that notifies the observer from the same context as where the observer was created?
Any help would be greatly appreciated!