Post

Replies

Boosts

Views

Activity

Reply to Recursively walk a directory using File Coordination
Your app’s role here is really about taking "reasonable" precautions (for example, immediatelyAvailableMetadataOnly isn't a bad option) and providing the user clear feedback about what you "did" (so the user can figure out if something went wrong). That makes sense as a philosophy to keep in the back of my head, thanks. I think using Task() for I/O work like this is probably a mistake. Ah, my mistake, I should’ve clarified that this would all be running inside a single actor, so the resulting behavior should be equivalent to an NSOperationQueue with a width of 1. However, if your goal is to actually maximize I/O, then what you really need is GCD's behavior (so you can use the CPU for "other stuff") but constrained to a much more reasonable number of threads (probably somewhere between "4" and "10"). I’ll make sure to keep this in mind when I start profiling. The problem with that is that each of those pending coordination requests consumes a Mach port Would this maybe be solved by reusing a single NSFileCoordinator() or by passing file access intents to coordinate(with:) in batches (as suggested by the docs)? Should I be doing that anyway? I’d rather avoid using the synchronous coordination API.
Oct ’25
Reply to Recursively walk a directory using File Coordination
Thank you for the detailed reply! So, the first question here is "what are you actually trying to do"? I’m adding a bulk import feature to my shoebox app. The user selects a folder, and the app walks the directory hierarchy looking for files of the type it supports (suppose they’re images for example’s sake). The app extracts image metadata by parsing the file, and then copies the image into a “Library” package if everything was successful. More the point, the "public" file system is also much more dynamic so the longer it takes to scan, the more likely it is that whatever you've scanned has ALREADY changed. The folder selected by the user is a user-visible one which may be dataless or have dataless contents. Ideally files would only be downloaded if they’re actually image files, which is why I brought up immediatelyAvailableMetadataOnly. This is a good point, though, thanks; I had this idea that I’d want to get a consistent snapshot of the entire hierarchy without any “tearing”, but I suppose there’s little reason to do that. I was thinking that I’d want to lock each file in a directory before I unlock the directory itself, but really why delay writes/moves/etc after the scan if that’ll mean the scan is out-of-date anyway? I'll warn you now, the words "implement the recursive walk myself" are a bit of a red flag. I’m aware of readattrlistbulk :) Using a shallow directory enumerator to get the contents seems like a good idea. So, would you say something like this would make sense (in pseudocode)? func scan(directory: URL) async { await coordinate(forReading: directory) for child in contents(of: directory) { if child.isDirectory { Task { await scan(directory: child) } } else { // don’t bother using immediatelyAvailableMetadataOnly? guard child.fileType == .image else { continue } // don’t block the directory scan on children completing, so spawn a new unstructured task Task { await coordinate(forReading: child) let photoMetadata = parseMetadata(child) let imageID = UUID() let urlInLibrary = PhotoLibrary.url.appending(imageID) copy(from: child, to: urlInLibrary) Persistence.add(imageID, metadata) } } } }
Oct ’25
Reply to NSScrollView scrolling hitch
I had a closer look at WebKit’s implementation, and they indeed ignore the system’s momentum scroll events, instead synthesizing their own using acceleration curves pulled from IOKit! This function has some interesting comments, and here’s where the acceleration curves are extracted. You might also find this commit intriguing.
Topic: UI Frameworks SubTopic: AppKit Tags:
Oct ’25
Reply to How can I bundle resources along with my launch agent?
[quote='841832022, Etresoft, /thread/786625?answerId=841832022#841832022, /profile/Etresoft'] A Launch Agent would run with a user space UI role. That's how Launch Agents work. That's not the same as a Launch Daemon that runs as root and does not require a login session. [/quote] Ah, you’re right! I feel a bit silly for not testing the null hypothesis earlier, but indeed even if I don’t embed my launch agent in an app bundle I still see the same output from taskinfo.
Jun ’25
Reply to Maintaining access to a folder across renames
From my testing FSEvents stops delivering events once the root has been changed, so creating a new event stream is necessary. AFAICT the documentation’s reason for recommending you keep around a file descriptor is only so that you can determine the root’s path after the rename, which in turn lets you create a new event stream.
Topic: Privacy & Security SubTopic: General Tags:
Apr ’25
Reply to Maintaining access to a folder across renames
My app monitors a folder selected by the user for internal changes with FSEvents, which sadly only takes a path, not a file descriptor. As a result, the “leave it open” approach doesn’t work for my use case. Instead, the app needs to respond immediately when the folder is renamed so it can destroy and recreate the necessary FSEvents event stream – hence the Dispatch source. The reason I feel security-scoped bookmarks are a bit of a hack here is that AFAIK they’re intended for persisting sandbox extensions across app launches, rather than within a single run of an app. Shouldn’t non-security-scoped bookmarks work here?
Topic: Privacy & Security SubTopic: General Tags:
Apr ’25
Reply to NSScrollView scrolling hitch
I’m so glad to see someone else mention this! I honestly thought I might be going crazy, thinking that inertia doesn’t feel quite right in NSScrollView. When scrolling a basic NSScrollView there seems to be a sudden jump after each flick. Scrolling does not appear smooth and is disorientating. I too have noticed this for years, and it’s always bothered me! A few months ago I tried to investigate these inconsistencies. It turns out that WebKit contains a custom reimplementation of NSScrollView which tries (and IMO succeeds) at being essentially indistinguishable from the real thing, except for the improved smoothness and faster scrolling speed, as you mentioned. I believe at least some of the hitches in AppKit you’re seeing aren’t down to rendering or view updates or anything like that, but simply because AppKit scroll event inertia is “stepped”: https://pavelfatin.com/images/scrolling-with-pleasure/scrolling-velocity.png. I think WebKit might also have a custom reimplementation of inertia (ignoring AppKit’s scroll inertia events, instead synthesizing its own), which would explain the difference. It, like every custom scroll view, also reimplements elasticity. As for responsive scrolling, I personally can’t tell the difference between NSScrollView with responsive scrolling enabled vs disabled.
Topic: UI Frameworks SubTopic: AppKit Tags:
Feb ’25
Reply to What are Dispatch workloops?
[quote='816385022, DTS Engineer, /thread/770062?answerId=816385022#816385022'] That’s about it. [/quote] I have to admit that I’m mildly disappointed! I’d kind of convinced myself that workloops must be some sort of dark magic. [quote='816385022, DTS Engineer, /thread/770062?answerId=816385022#816385022'] Because the workloop is intended to be the target, not the source, of work. The idea is to have one workloop per subsystem and then have various serial queue, or serial queue hierarchies, target that. [/quote] This makes sense, thank you! I can see how workloops map well onto the ideas presented in the WWDC session you linked. Keep using serial queues where ordering matters, otherwise target everything at one workloop (instead of a serial queue) per subsystem. [quote='816385022, DTS Engineer, /thread/770062?answerId=816385022#816385022'] Honestly, if you could set a target queue I’m not sure how that’d even work. If you set a workloop’s target queue to a serial queue, you’d be back in FIFO Land™. [/quote] I was imagining that targeting a workloop at a serial queue would interleave the workloop’s work items (which are still ordered by priority) with the serial queue’s other work items (which maintain their ordering); it’s as if you’d targeted one serial queue at another, except that the first queue happens to have had its work submitted in descending priority order. Targeting a workloop at another workloop would function in the same way as how targeting a serial queue at a workloop does today, minus the ordering requirement. I suppose the purpose of this would be the same as why we target serial queues at one another: to apply labels for debugging and to assign QoS classes. Of course, none of this matters since I’m just imagining things. [quote='816385022, DTS Engineer, /thread/770062?answerId=816385022#816385022'] ps I love your blog! [/quote] Thank you for the compliment and for the fantastic answers!
Dec ’24