Post

Replies

Boosts

Views

Activity

SwiftUI ReferenceFileDocument and Document-scoped bookmarks
Context I'm writing an app that allows a user to select folders, and then scan them for files. The folder could be on the user's machine, iCloud or external storage. The app persists the details of these files and folders to a document, so the user can access the files or re-scan the folders in the future. The App is being written using the SwiftUI framework for MacOS and the iPad. Problems Given this is a Sandboxed app I need to create security-scoped bookmarks to be able to access the files and folders that have been persisted to the document. I have two questions: How can I create a document-scoped bookmark, when using ReferenceFileDocument protocol. I need the document's URL, but I will never have access to this as I'm using the ReferenceFileDocument. I want to achieve something like this:   func fileWrapper(snapshot: MyDocument, configuration: WriteConfiguration) throws - FileWrapper { : let bookmarkDataToPersist = snapshort.sourceFolderURL.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: documentURL) : } 2. Ideally the user would be able to: * connect an external drive to their Mac * select a folder on that drive * save the document, which would persist a bookmark to that folder's URL * send the document to an iPad (via email or iCloud drive) * open the document using the iPad version of the App * connect the external bookmark to the iPad * re-scan the folder which was book marked in the document from the folder But given the problem in 1) and the fact that document-bookmarks cannot point to folders, is there a way? Any ideas or suggestions would be very welcome
0
0
607
Apr ’21
Monterey / SwiftUI view not updating as expecting
The following code is stripped out from an app that compiles and works under MacOS 11. It shows a tab bar - clicking on an item will highlight it. Under the tab bar is a text edit field where one can edit the title of the selected tab. There are 2 issues: The tab title shown in the title editor is allows out of phase from the selected tab Irrespective of which tab item is selected, when the title is edited it always updates the first tab I'm not sure if I was very lucky that this code ever worked under Big Sur, or if there is an issue with Monterey. I'm definitely not holding this up as example code - I'm sure there are better ways to implement it, but seek opinions on whether it should work. import SwiftUI class Document: ObservableObject { var tabs = [Tab(id: 0), Tab(id: 1)] var viewSettings = ViewSettings() } class Tab: ObservableObject, Identifiable { let id: Int @Published var title: String init(id: Int) { self.id = id self.title = "Tab \(id)" } } class ViewSettings: ObservableObject { @Published var activeTab: Int = 0 } @main struct Test: App { @StateObject var document: Document = Document() var body: some Scene { WindowGroup { ContentView() .padding() .environmentObject(document) .environmentObject(document.viewSettings) } } } struct ContentView: View { @EnvironmentObject var document: Document @EnvironmentObject var viewSettings: ViewSettings var body: some View { TabBar(viewSettings: document.viewSettings) TabEditView(activeTab: document.tabs[viewSettings.activeTab]) } } struct TabEditView: View { @EnvironmentObject var viewSettings: ViewSettings @ObservedObject var activeTab: Tab @State var title: String = "" init(activeTab: Tab) { print("CONSOLE - Init TabEditView for tab \(activeTab.id)") self.activeTab = activeTab } var body: some View { HStack { Text("Tab title:") TextField("Tab title:", text: $title, onCommit: { activeTab.title = title }) .onAppear { title = activeTab.title } .onChange(of: viewSettings.activeTab) { _ in print("CONSOLE - Updating TextField from tab \(activeTab.id)") title = activeTab.title } } } } struct TabBar: View { @EnvironmentObject var document: Document @ObservedObject var viewSettings: ViewSettings var body: some View { HStack { ForEach(document.tabs, content: TabItem.init) } } } struct TabItem: View { @EnvironmentObject var viewSettings: ViewSettings @ObservedObject var tab: Tab init(_ tab : Tab) { self.tab = tab } var body: some View { Text(tab.title) .padding(2) .background(tab.id == viewSettings.activeTab ? .red : .clear) .cornerRadius(4) .onTapGesture { viewSettings.activeTab = tab.id } } }
0
0
657
Jul ’21
Conforming an actor to Sequence protocol
How can one conform an actor to the Sequence protocol? The following code generates the compiler warning: Instance method 'makeIterator()' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Sequence'. @MainActor class Test: Sequence { private var contents: [Int] = [] func makeIterator() -> Array<Int>.Iterator { contents.makeIterator() } }
0
0
881
Aug ’21
Swift value type semantics and impact of bindings
I was recently looking at Apple's sample code for a ReferenceFileDocument based SwiftUI document app: Building a Document-Based App with SwiftUI The two main data types, Checklist and ChecklistItem, are defined as structs. There is also a helper struct BindingCollection that converts a binding to a collection of elements into a collection of bindings to the individual elements. The app relies on bindings to these structs. However, in some ways, isn't a binding to a struct circumnavigating value-type semantics? Any piece of code that is passed the Binding can alter the value, rather than a copy of the value? How does SwiftUI know that the struct has been updated without a publisher? Last question: if I'd been writing this app myself, I would have made Checklist a class, conforming to ObservableObject publishing its items property. This would have avoided the helper function, and use of bindings. What are the benefits of the struct / binding approach in the example code?
0
0
782
Aug ’21
GCD TSAN issue: Data race in generic specialization <Foundation.UUID>
The XCODE TSAN thread analyser is throwing up a threading issue: Data race in generic specialization <Foundation.UUID> of Swift._NativeSet.insertNew(_: __owned τ_0_0, at: Swift._HashTable.Bucket, isUnique: Swift.Bool) -> () at 0x10a16b300 This only occurs in a release build, and its Data race in generic specialization that has my attention. It pin-points the addID function. But I cannot see the issue. Here is the relevant code snippet: final class IDBox { let syncQueue = DispatchQueue(label: "IDBox\(UUID().uuidString)", attributes: .concurrent) private var _box: Set<UUID> init() { self._box = [] } var box: Set<UUID> { syncQueue.sync { self._box } } func addID(_ id: UUID) { syncQueue.async(flags: .barrier) { self._box.insert(id) } } }
0
0
722
May ’22
GlobalActor directive doesn't guarantee a function will be called on that actor?
Assuming I have defined a global actor: @globalActor actor MyActor { static let shared = MyActor() } And I have a class, in which a couple of methods need to act under this: class MyClass { @MyActor func doSomething(undoManager: UndoManager) { // Do something here undoManager?.registerUndo(withTarget: self) { $0.reverseSomething(undoManager: UndoManager) } } @MyActor func reverseSomething(undoManager: UndoManager) { // Do the reverse of something here print(\(Thread.isMainThread) /// Prints true when called from undo stack undoManager?.registerUndo(withTarget: self) { $0.doSomething(undoManager: UndoManager) } } } Assume the code gets called from a SwiftUI view: struct MyView: View { @Environment(\.undoManager) private var undoManager: UndoManager? let myObject: MyClass var body: some View { Button("Do something") { myObject.doSomething(undoManager: undoManager) } } } Note that when the action is undone the 'reversing' func it is called on the MainThread. Is the correct way to prevent this to wrap the undo action in a task? As in: @MyActor func reverseSomething(undoManager: UndoManager) { // Do the reverse of something here print(\(Thread.isMainThread) /// Prints true undoManager?.registerUndo(withTarget: self) { Task { $0.doSomething(undoManager: UndoManager) } } }
0
0
1k
Jul ’22
Issues testing StoreKit in Xcode after AppBundle ID change
I'm developing across two Macs: one Apple Silicon and an Intel laptop (used for performance and compatibility testing). I've been testing my StoreKit2 implementation, and have come across a couple of issues. From time to time something appears to become corrupted, and StoreKit2 says it has a 'connection' issue. Deleting the folder com.apple.storekitagent, which a sub folder Octane, restarting the machine appears to fix this. The second issue I cannot appear to resolve. I have needed to change the App Bundle ID. I did this whilst developing on the M2 Mac without problem. But now when I try and run back on the Intel Mac I am getting a set of unfinished transactions which I can either process, nor delete (they are not appearing in Xcode's StoreKit debug window. I've tried deleting the folder com.apple.storekitagent, and restarting the machine, but to no avail. Note if I reset back to my original App Bundle ID then all works as before. Here is a sample of errors I am receiving: Error finishing transaction 110: Error Domain=ASDErrorDomain Code=500 "Unhandled exception" UserInfo={NSUnderlyingError=0x600001863cf0 {Error Domain=AMSErrorDomain Code=301 "Invalid Status Code" UserInfo={NSLocalizedDescription=Invalid Status Code, AMSURL=http://localhost:49242/WebObjects/MZFinance.woa/wa/inAppTransactionDone?REDACTED, AMSStatusCode=404, AMSServerPayload={ error = "Transaction not found"; }, NSLocalizedFailureReason=The response has an invalid status code}}, storefront-country-code=USA, client-environment-type=XcodeTest(file:///Users/peggers/Library/Caches/com.apple.storekitagent/Octane/com.bristolbaycodefactory.photo-organista/), AMSServerErrorCode=0, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception} Any further ideas on how to reset or solve this issue?
0
1
1.1k
Mar ’23
Passing locale into a RegexBuilder as a parameter
I am building a tokeniser, and would like to hold this as a struct, passing in a locale during initiation. Here's the gist of what I would want to write: struct Tokeniser { private let locale: Locale private let integerRegex: Regex init(locale: Locale) { self.locale: Locale self.integerRegex = Regex { Capture { .localizedInteger(locale: locale) } transform: { Token.number($0) } } } func parse(text: String) -> Token { if let match = try integerRegex.firstMatch(in: text) { //... other code here } } \\...other code here } As Regex is generic the compiler suggests to set the integerRegex's type to Regex<Any>, but this triggers another set of compiler issues that I have not been able to figure out what the type should be. So then I tried to write something like this (inspired by SwiftUI): var integerRegex: some Regex { Capture { .localizedInteger(locale: locale) } transform: { Token.number($0) } } But again, the compiler prompts me to enter Regex. The only way I have to be able to get the struct to compiler is to create lazy variables, which then have the side effect that I have to mark my functions as mutable, which have downstream issues when they are called from with SwiftUI structs. lazy var integerRegex = Regex { Capture { .localizedInteger(locale: locale) } } mutating func parse(text: String) -> Token { if let match = try integerRegex.firstMatch(in: text) { } } How can I code this?
0
0
511
Oct ’23
Updating metadata properties of a DNG (or other) format image
Hi, I'm looking to update the metadata properties of a DNG image stored on disc, saving to a new file. Using ImageIO's CGImageSource and CGImageDestination classes, I run into a problem where by the destination doesn't support the type of the source. For example: let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary if let cgImageSource = CGImageSourceCreateWithURL(sourceURL as CFURL, imageSourceOptions), let type = CGImageSourceGetType(cgImageSource) { guard let imageDestination = CGImageDestinationCreateWithURL(destinationURL as CFURL, type, 1, nil) else { fatalError("Unable to create image destination") } // Code to update properties and write out to destination url } } When this code is executed I get the following errors on the command line when trying to create the destination: 2024-06-30 11:52:25.531530+0100 ABC[7564:273101] [ABC] findWriterForTypeAndAlternateType:119: *** ERROR: unsupported output file format 'com.adobe.raw-image' 2024-06-30 11:52:25.531661+0100 ABC[7564:273101] [ABC] CGImageDestinationCreateWithURL:4429: *** ERROR: CGImageDestinationCreateWithURL: failed to create 'CGImageDestinationRef' I don't see a way to create a destination directly from a source? Yes, the code works for say a JPEG file but I want it to work for any image format that CGImageSource can work with?
0
0
738
Jun ’24
Custom EntityAction - different behaviour VisionOS 2.6 vs 26
I implemented an EntityAction to change the baseColor tint - and had it working on VisionOS 2.x. import RealityKit import UIKit typealias Float4 = SIMD4<Float> extension UIColor { var float4: Float4 { if cgColor.numberOfComponents == 4, let c = cgColor.components { Float4(Float(c[0]), Float(c[1]), Float(c[2]), Float(c[3])) } else { Float4() } } } struct ColourAction: EntityAction { // MARK: - PUBLIC PROPERTIES let startColour: Float4 let targetColour: Float4 // MARK: - PUBLIC COMPUTED PROPERTIES var animatedValueType: (any AnimatableData.Type)? { Float4.self } // MARK: - INITIATION init(startColour: UIColor, targetColour: UIColor) { self.startColour = startColour.float4 self.targetColour = targetColour.float4 } // MARK: - PUBLIC STATIC FUNCTIONS @MainActor static func registerEntityAction() { ColourAction.subscribe(to: .updated) { event in guard let animationState = event.animationState else { return } let interpolatedColour = event.action.startColour.mixedWith(event.action.targetColour, by: Float(animationState.normalizedTime)) animationState.storeAnimatedValue(interpolatedColour) } } } extension Entity { // MARK: - PUBLIC FUNCTIONS func changeColourTo(_ targetColour: UIColor, duration: Double) { guard let modelComponent = components[ModelComponent.self], let material = modelComponent.materials.first as? PhysicallyBasedMaterial else { return } let colourAction = ColourAction(startColour: material.baseColor.tint, targetColour: targetColour) if let colourAnimation = try? AnimationResource.makeActionAnimation(for: colourAction, duration: duration, bindTarget: .material(0).baseColorTint) { playAnimation(colourAnimation) } } } This doesn't work in VisionOS 26. My current fix is to directly set the material base colour - but this feels like the wrong approach: @MainActor static func registerEntityAction() { ColourAction.subscribe(to: .updated) { event in guard let animationState = event.animationState, let entity = event.targetEntity, let modelComponent = entity.components[ModelComponent.self], var material = modelComponent.materials.first as? PhysicallyBasedMaterial else { return } let interpolatedColour = event.action.startColour.mixedWith(event.action.targetColour, by: Float(animationState.normalizedTime)) material.baseColor.tint = UIColor(interpolatedColour) entity.components[ModelComponent.self]?.materials[0] = material animationState.storeAnimatedValue(interpolatedColour) } } So before I raise this as a bug, was I doing anything wrong in the former version and got lucky? Is there a better approach?
0
0
89
Sep ’25
VideoPlayer crashes on Archive build
I have found that following code runs without issue from Xcode, either in Debug or Release mode, yet crashes when running from the binary produced by archiving - i.e. what will be sent to the app store. import SwiftUI import AVKit @main struct tcApp: App { var body: some Scene { WindowGroup { VideoPlayer(player: nil) } } } This is the most stripped down code that shows the issue. One can try and point the VideoPlayer at a file and the same issue will occur. I've attached the crash log: Crash log Please note that this was seen with Xcode 26.2 and MacOS 26.2.
0
0
68
2d