Post

Replies

Boosts

Views

Activity

Reply to NSFileManager getRelationship:ofDirectoryAtURL:toItemAtURL:error: returning NSURLRelationshipSame for Different Directories
ACTUALLY doing #2 for every call is a terrible idea for both performance and coherence issues, but that means we're basically stuck trying to sort out when to reset, not if we're going to cache. I agree. IMO the problem is not that NSURL is caching the problem is the way it caches. The way it caches forces me to cache on top of it. The documentation claims it only caches for 1 run loop turn but as previously mentioned that is not always the case and certain values tend to get 'stuck.' Building a cache on top of NSURL resource values which may or may not be stale can cause all sorts of weird behavior if you don't call -removeCacheResourceValues so I can cache on the true value...but NSURL I assume makes its cache thread safe so -removeCacheResourceValues probably isn't so cheap. Doesn't that mean the url cache is costing me performance by requiring me to clear it to get to the true values I really want to cache? Huh. That's really weird. How did you construct those URLs? Originally the URL came through NSFIlemanager enumeration, or maybe -createDirectoryAtURL: I can't remember. I'll have to try it out later when I have a little bit more time. But I just stumbled across some really weird behavior when passing a file type from Finder to my app. It could be unrelated but I wouldn't be completely surprised if it was related to this topic. I might file a bug on that later. It would be great if this forum supported private messages I'm not sure if I'm ready to provide more details yet in the open
Topic: App & System Services SubTopic: Core OS Tags:
Feb ’26
Reply to Creating a Temporary Directory with NSFileManager - NSItemReplacementDirectory creates folder in user-facing location?
The API I'm using to write the file (to the temp location) writes the file atomically and will overwrite an existing file but in the final destination I'm working in it is a user facing folder and I don't want to just assume a save location and potentially overwrite the user's data. So what I do is simply write in the temporary location atomically, then attempt to move the file in the final destination with a preferred filename without looking before I leap and if I fail to move because the file already exists, I try again with a different name. I could continue to write to the temporary location the old way but that definitely will be slower for external volumes because I do the "move" (copy/delete) across volumes. But I don't want to flash temporary folders in the Finder either. In my very limited testing it seems if I clean up the temp directory right after I finish they don't appear in Finder but I assume they will if the operation takes a long time.
Topic: App & System Services SubTopic: General Tags:
Feb ’26
Reply to NSFileManager getRelationship:ofDirectoryAtURL:toItemAtURL:error: returning NSURLRelationshipSame for Different Directories
Thanks for the reply! I actually stumbled across this while reworking things in my app to account for NSURL caching behavior I mentioned in the other thread. What I was doing not too long ago was using an NSCache on top of NSURL for resource values. At some point when responding to metadata changes I was calling -removeCacheResourceValues on a background thread to get refreshed data and I had discovered that -removeCacheResources could crash if another thread was reading at the same time. I guess at some point in my frustration I just moved some stuff around to stop the crashes (and I did). I had either forgotten or just never realized that NSURL caches only for a run loop turn (or maybe just sometimes? More on that in a second). I guess this is cool in the middle of a dragging session but apparently at some point I must've just assumed that NSURL must be caching for a more meaningful period of time (from the perspective of my app anyway) because if I didn't call -removeCachedResources I'd get stale values sometimes. SO why cache on top of a cache? And I chucked my NSCache which I never really loved but apparently that was a mistake. My bad. I guess my wish would be for NSURL to either cache forever until explicitly clear values or don't cache at all because if we're caching on a cache that may not be a cache but sometimes it seems like a cache it's hard to cache. Maybe I'm just being selfish though. But back to the collision. So I'm reworking all this (not using NSCache this time). Now as I'm rewriting my caching code I commented out few things here and there checking some error handling code paths that seem extremely unlikely to really occur and I stumble across this collision but there are many run loop turns in between these events so I don't understanding why the cached values are living for so long in this particular case. Maybe something like cancelPreviousPerformRequestsWithTarget causes cached values to live longer but I'm not suppose to worry about the implementation details. I can easily reproduce this with NSFileManager using the following steps: -trashItemURL:resultingItemURL: - grab the resultingItemURL. Put an empty new folder in the exact same location you just trashed. Compare the NSURLFileResourceIdentifierKey of the URLs you got from resultingItemURL with new folder at its old location and they match - until you programmatically remove the cached value.
Topic: App & System Services SubTopic: Core OS Tags:
Feb ’26
Reply to Appkit without storyboards XCode 26.2
@hieronim-bosch AppKit is my favorite framework, nothing else comes close. Until proven otherwise there is still no better way to make a Mac app IMHO. That said I never got into Storyboards on Mac. In Xcode 26.2 I can still create an AppKit project the "old way" which is New Project -> macOS -> App then change Interface to XIB then you get a project without a storyboard. If you want to go completely without Interface Builder you can but I don't think Apple ever had a template for that setup (well if they did I never noticed or it must have been a really long time ago). You can set the NSApplication delegate in main. #import <Cocoa/Cocoa.h> @interface AppDelegate : NSObject <NSApplicationDelegate> @property (strong) NSWindowController *mainWindowController; @end @implementation AppDelegate -(void)applicationDidFinishLaunching:(NSNotification*)aNotification { NSLog(@"Hello world!"); NSWindow *firstWindow = [[NSWindow alloc]initWithContentRect:NSMakeRect(50.0, 50.0, 400.0, 400.0) styleMask:NSWindowStyleMaskTitled backing:NSBackingStoreBuffered defer:NO]; firstWindow.title = @"Xibless"; self.mainWindowController = [[NSWindowController alloc]initWithWindow:firstWindow]; [self.mainWindowController showWindow:nil]; } @end // main.m int main(int argc, const char * argv[]) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; AppDelegate *appDelegate = [[AppDelegate alloc]init]; app.delegate = appDelegate; [app setActivationPolicy:NSApplicationActivationPolicyRegular]; [app run]; } } and I think you also need to build the menu bar programmatically. IMO there really is no reason to do all this. If you want to avoid Interface Builder I think it's more reasonable to just do the following: Create an Xib project. Keep the MainMenu.xib but inside it delete the window but leave the menu bar. Then in your AppDelegate just make your NSWindowController / NSWIndow in code. Then you're mostly without IB - enough for learning. Or if you want you can build the menu bar (see mainMenu property on NSApplication: https://developer.apple.com/documentation/appkit/nsapplication/mainmenu?language=objc).
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
Also CFURL is documented to have different behavior but CFURL and NSURL aren't they 'toll free bridged' so how does that work if you cast a CFURL to a NSURL? So I just did a dumb little test to answer this. I created a CFURLRef and read kCFURLIsHiddenKey and got false (as expected) so it would cache it. Then on another CFURL instance (that points to the same file) I did the same thing (so it was cache the value). After that I set hidden to YES: NSURL *toNSURL = (__bridge NSURL * _Nonnull)cfURL; [toNSURL setResourceValue:@(YES) forKey:NSURLIsHiddenKey error:nil]; Then back to the other instance I cast that one to another NSURL: NSURL *nsCastCopiedVersion = (__bridge NSURL * _Nonnull)aCopiedCFURL; And read isHidden and it is NO. Read aCopiedCFURL hidden and it is also NO. Then dispatch after dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [URLPrinter printCF:aCopiedCFURL]; [URLPrinter printNS:nsCastCopiedVersion]; }); And got: Print copied CF Not hidden // cached value - real value is true. Print copied NSCF: Hidden // hidden true value So indeed using CFURL instead would seem to avoid this. Learn something new every day. Now if I didn't already have a million lines of code already using NSURL I would just use CF instead (still might) because at least for my app I find dumping cache values at every run loop churn undesirable. I did have a better caching system implemented at some point but seems some of it got dumped it when I implemented a workaround to avoid -removeCacheResourceValue: crashes a couple of years ago. It'll all be back in biz soon. Thanks for the help guys.
Topic: App & System Services SubTopic: General Tags:
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
When you access a property on the main thread, the system checks to see if the cached value is still valid, that is, has the main thread ‘turned’ between when you last got the property and now. I see. IMHO binding cache invalidation to the turning of a run loop while simultaneously recommending accessing -getResourceValue:forKey: on a background queue feels somewhat peculiar but I guess that peculiarity came during that long evolution. The main benefit of caching just until the run loop turns I guess would help if you were continuously calling -getResourceValue:forKey: in loop or in the middle of event handling but I wouldn't expect that to be so common given the recommendation to call -getResourceValue:forKey: off the main thread when possible. The downside with this short lived cache is that other threads can read stale values from -getResourceValue:forKey: calls unless they explicitly clear the cache using -removeCachedResourceValueForKey: etc. but using those methods wasn't always safe but hopefully they are now. I was working on just getting metadata I need with other APIs and caching them but there are some important resource values I need that seemingly are only available through the NSURL apis :)
Topic: App & System Services SubTopic: General Tags:
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
So I've discovered if you create the NSURL on a background thread you can get stale resource values even on the next churn of the run loop. But whose run loop 'owns' the URL resources? The main thread's run loop ? The run loop of the thread the URL was created on? Or does NSURL do something like this: - (BOOL)getResourceValue:(out id _Nullable * _Nonnull)value forKey:(NSURLResourceKey)key error:(out NSError ** _Nullable)error API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)); { // do whatever to get the resource value //-- // schedule delete from cache. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(clearResourceValueForKey:) object:key]; [self performSelector:@selector(clearResourceValueForKey:) withObject:key afterDelay:0.0]; } I don't see how you can tie cached resource value state to a run loop - it doesn't make any sense to me, especially since the documentation advises doing file operations on a background thread/queue because hitting the disk can be slow. What if I'm sorting an array of NSURLs by some metadata on a background thread and the main thread run loop is just happily invalidating the cache resources behind my back? Maybe I'm not understanding something. IMO I think better behavior would be just to cache on first access and keep it until I explicitly invalidate it but I guess I have to use CFURL for that. I think it makes more sense to let the developer flush the cache in response to file coordination or whatever API being used to monitor the URL but I guess I have to build a cache on top of the cache.
Topic: App & System Services SubTopic: General Tags:
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
Thanks for responding. I haven't yet been able to reproduce the issue in a small test project so either they made changes in a macOS update or there is some timing issue and/or way the NSURL is initialized in my real project teases the issue out. But I promise I got stale value for nonexistent NSURLIsHiddenKey until I started explicitly dumping it. In my real project the URL comes for -fileURLWithPath: (and initially created on a background thread). My real project is large and complex so when I have more time I'll have to see if I can isolate the issue in a small sample. Due the request by iOS and the server cache the user may see some discrepancies or additional nuances in how and caching behave, particularly regarding stale values. I'm on macOS. Explicit cache management is recommended, especially when dealing with URLs that may have changed state (e.g., deleted or modified), to ensure your application behaves predictably across different environments and runtime sessions. Also CFURL is documented to have different behavior but CFURL and NSURL aren't they 'toll free bridged' so how does that work if you cast a CFURL to a NSURL? I would certainly prefer explicit cache management. Chucking cached resource values at every churn of the run loop seems silly and IMO could cause unintended performance issues because the next time the app asks for the cache resource value I presume we hit the disk unnecessarily when nothing has changed. Chucking cached values at every churn of the run loop really reduces the benefits of caching in the first place - developers have to cache on top of the cache but you don't know what's cache? The only way to be sure you don't get a stale value is to call -removeCacheResourceValue methods, which again seems to reduce the benefits of NSURL caching in the first place. Also the problem with explicit cache management is I don't know if resource values are shared across NSURL instances. In the past I had a talk with an Apple badged person and I think he told me it was (or could be at that time but I'll have to check notes). At that time I discovered that calls to -removeResourceValueForKey and/or -removeAllCachedResourceValues could cause crashes. Do you know if each NSURL instance gets its own isolated cache or are they still shared by NSURLs that point to the same file (which I don't think would be safe)?
Topic: App & System Services SubTopic: General Tags:
Jan ’26
Reply to How can I be notified if another app goes full screen on macOS?
If there is a way to get notified when another app goes full screen, I'm unaware of it. If it isn't appropriate for your status windows to ever be displayed in full screen mode have you tried using NSWindowCollectionBehaviorFullScreenNone on these windows? I have a window that should display in full screen sometimes, and like you I want to be polite and initially hide it. I've been using a hack forever to do this which mostly works but it isn't exactly pretty. It involves creating a hidden window with a certain collectionBehavior like NSWindowCollectionBehaviorFullScreenNone | NSWindowCollectionBehaviorCanJoinAllSpace and basically track if the active space contains this window. If it doesn't I assume the active space contains an app with a full screen window. Again not perfect but it's the best I could think of. If there is a better way to do it, I'd also like to know.
Topic: UI Frameworks SubTopic: AppKit Tags:
Jan ’26
Reply to AppKit - Legal to Change a View's Frame in -viewDidLayout?
Thanks a lot for responding. Thanks for the post, it’s hard not seeing the code and how you're setting constrains in code. Would you be so kind to provide your code where you setting the constraints so developers here can see it? [..] it is generally not a good idea (and will lead to crashes) to directly modify the frame or bounds of a view that is managed by Auto Layout in my opinion. Initially I did not involve Autolayout at all explicitly. What I had was a small container view controller with something like this (no explicit constraints): @implementation SmallInfoWrapperViewController -(void)viewDidLayout { [super viewDidLayout]; NSRect bounds = self.view.bounds; CGFloat lineHeight = 1.0; self.separator.frame = NSMakeRect(0.0,bounds.size.height-lineHeight,bounds.size.width,lineHeight); BOOL separatorVisible = !self.separator.isHidden; CGFloat wrappedViewHeight = bounds.size.height; if (separatorVisible) { wrappedViewHeight -= lineHeight; } self.wrappedView.frame = NSMakeRect(0.0,0.0,bounds.size.width, wrappedViewHeight); } @end That was fine when wrappedView was an NSScrollView (which contains an NSOutlineView). The NSScrollView/OutlineView/Clipview triplet comes out of a xib which is many years old that also has no explicit Autolayout constraints. All worked fine. Once wrappedView became an NSGlassEffectView (which now contains the scroll view) that is when Autolayout said it needed to break constraints the system was creating from autoresizing masks and it listed weird fixed width and height constraints. I find Autolayout useful but avoided it in certain situations where it seems unnecessary it could overcomplicate and the task was so easy (like this one) it felt like cutting a stick of butter with a chainsaw. But the system seems to be trying to make Autolayout somewhat of a requirement so rather than try to fight it I just gave in. self.wrappedView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[leading, trailing, bottom, top]]; But I initially forgot to remove self.wrappedView.frame from -viewDidLayout which is when I hit the exception. Fix is to instead modify the constant of the top constraint when separator.isHidden changes instead. So I already knew what caused the issue and how to fix it but the exception: "The window has been marked as needing another Layout Window pass, but it has already had more Layout Window passes than there are views in the window" did make me curious enough to ask this question because it doesn't seem so uncommon/unreasonable to make adjustments in -layout and -viewDidLayout. Something like: -(void)layout { [super layout]; [self.dateLabel sizeToFit]; if (![self doesDateLabelFitAtNaturalWidth]) { [self useShorterDateStyleLayout]; } } Of course the above is just "concept code" but shrinking a control based on available space in certain situations is more straightforward and easier to maintain in manual layout than with Autolayout. Most of the time Autolayout is preferred, I agree. In any case it doesn't feel appropriate for the system to generate width and height constraints from autoresizing masks ever (perhaps I have a naive point of view but that looks like it could cause some real trouble to me). IMO it makes sense to generate leading, trailing, top and bottom constraints but width/height I'm not sure about that. There was like some weird 250 point min width constraint or something and I have no idea how that possibly could have been calculated from autoresizing masks. In another area I had to fix I also ran into a min width constraint conflict when I downsized a window width because the generated constraint from an autoresizing mask somehow created a weird min width 50 constraint that was too big for the really small window size. Overall it now seems somewhat dicey to set frames in -viewDidLayout / layout overrides because even if you aren't using constraints explicitly it is difficult to determine what the system is generating under the covers. What do you mean by legal? What I mean by legal is safe to modify and supported. In my opinion I think there should be a point (like UIKit -viewDidLayoutSubviews) where layout can be safely modified with or without explicit Autolayout constraints to give developers maximum control (even though rarely needed). I don't really understand why the system doesn't permit a more hands off approach like this: self.lockLayoutInvalidation = YES; [self doAutolayoutOnSubTree]; [self callViewDidLayout]; self.lockLayoutInvalidation = NO; Whatever the layout is after viewDidLayout - it is what it is. Any overlapping views or mistakes or whatever leave it on the developer to find and fix but crashing, throwing, etc. seems a bit much.
Topic: UI Frameworks SubTopic: AppKit Tags:
Jan ’26
Reply to macOS Tahoe WKWebView - NSPrintOperation EXC_BREAKPOINT with Lots of Error Logging
Thanks for replying. Sure. NSPrintOperation *printOp = [self.webView printOperationWithPrintInfo:[NSPrintInfo sharedPrintInfo]]; if (printOp == nil) { os_log_fault(OS_LOG_DEFAULT, "Nil print operation."); return; } if (self.view.window != nil) { [printOp runOperationModalForWindow:self.view.window delegate:self didRunSelector:@selector(myPrintOperationDidRun:success:contextInfo:) contextInfo:nil]; }
Topic: UI Frameworks SubTopic: AppKit Tags:
Jan ’26
Reply to NSFileManager getRelationship:ofDirectoryAtURL:toItemAtURL:error: returning NSURLRelationshipSame for Different Directories
ACTUALLY doing #2 for every call is a terrible idea for both performance and coherence issues, but that means we're basically stuck trying to sort out when to reset, not if we're going to cache. I agree. IMO the problem is not that NSURL is caching the problem is the way it caches. The way it caches forces me to cache on top of it. The documentation claims it only caches for 1 run loop turn but as previously mentioned that is not always the case and certain values tend to get 'stuck.' Building a cache on top of NSURL resource values which may or may not be stale can cause all sorts of weird behavior if you don't call -removeCacheResourceValues so I can cache on the true value...but NSURL I assume makes its cache thread safe so -removeCacheResourceValues probably isn't so cheap. Doesn't that mean the url cache is costing me performance by requiring me to clear it to get to the true values I really want to cache? Huh. That's really weird. How did you construct those URLs? Originally the URL came through NSFIlemanager enumeration, or maybe -createDirectoryAtURL: I can't remember. I'll have to try it out later when I have a little bit more time. But I just stumbled across some really weird behavior when passing a file type from Finder to my app. It could be unrelated but I wouldn't be completely surprised if it was related to this topic. I might file a bug on that later. It would be great if this forum supported private messages I'm not sure if I'm ready to provide more details yet in the open
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Feb ’26
Reply to Creating a Temporary Directory with NSFileManager - NSItemReplacementDirectory creates folder in user-facing location?
The API I'm using to write the file (to the temp location) writes the file atomically and will overwrite an existing file but in the final destination I'm working in it is a user facing folder and I don't want to just assume a save location and potentially overwrite the user's data. So what I do is simply write in the temporary location atomically, then attempt to move the file in the final destination with a preferred filename without looking before I leap and if I fail to move because the file already exists, I try again with a different name. I could continue to write to the temporary location the old way but that definitely will be slower for external volumes because I do the "move" (copy/delete) across volumes. But I don't want to flash temporary folders in the Finder either. In my very limited testing it seems if I clean up the temp directory right after I finish they don't appear in Finder but I assume they will if the operation takes a long time.
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Feb ’26
Reply to NSFileManager getRelationship:ofDirectoryAtURL:toItemAtURL:error: returning NSURLRelationshipSame for Different Directories
Thanks for the reply! I actually stumbled across this while reworking things in my app to account for NSURL caching behavior I mentioned in the other thread. What I was doing not too long ago was using an NSCache on top of NSURL for resource values. At some point when responding to metadata changes I was calling -removeCacheResourceValues on a background thread to get refreshed data and I had discovered that -removeCacheResources could crash if another thread was reading at the same time. I guess at some point in my frustration I just moved some stuff around to stop the crashes (and I did). I had either forgotten or just never realized that NSURL caches only for a run loop turn (or maybe just sometimes? More on that in a second). I guess this is cool in the middle of a dragging session but apparently at some point I must've just assumed that NSURL must be caching for a more meaningful period of time (from the perspective of my app anyway) because if I didn't call -removeCachedResources I'd get stale values sometimes. SO why cache on top of a cache? And I chucked my NSCache which I never really loved but apparently that was a mistake. My bad. I guess my wish would be for NSURL to either cache forever until explicitly clear values or don't cache at all because if we're caching on a cache that may not be a cache but sometimes it seems like a cache it's hard to cache. Maybe I'm just being selfish though. But back to the collision. So I'm reworking all this (not using NSCache this time). Now as I'm rewriting my caching code I commented out few things here and there checking some error handling code paths that seem extremely unlikely to really occur and I stumble across this collision but there are many run loop turns in between these events so I don't understanding why the cached values are living for so long in this particular case. Maybe something like cancelPreviousPerformRequestsWithTarget causes cached values to live longer but I'm not suppose to worry about the implementation details. I can easily reproduce this with NSFileManager using the following steps: -trashItemURL:resultingItemURL: - grab the resultingItemURL. Put an empty new folder in the exact same location you just trashed. Compare the NSURLFileResourceIdentifierKey of the URLs you got from resultingItemURL with new folder at its old location and they match - until you programmatically remove the cached value.
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Feb ’26
Reply to Spotlight Shows "Helper Apps" That Are Inside Main App Bundle That Are Not Intended to Be Launched By The User
To add the main app also declares services (which are still visible) after the macOS update - but the helper app services do not appear. Related Feedback from September: FB20356742
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Feb ’26
Reply to Spotlight Shows "Helper Apps" That Are Inside Main App Bundle That Are Not Intended to Be Launched By The User
So I updated my VM from macOS Tahoe 26.0 BETA to macOS Tahoe 26.2 and the services disappeared. I guess I wasn't totally crazy in my concern about this. Unfortunately when a reply gets "Apple recommended" I can't unaccept an answer and I guess my TSI just got unceremoniously closed.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Feb ’26
Reply to Spotlight Shows "Helper Apps" That Are Inside Main App Bundle That Are Not Intended to Be Launched By The User
I did get a report about the Service not showing up now that I changed the path. I naturally haven't been able to reproduce on my end and I'm still trying to get more details from the user about his configuration.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Feb ’26
Reply to Appkit without storyboards XCode 26.2
@hieronim-bosch AppKit is my favorite framework, nothing else comes close. Until proven otherwise there is still no better way to make a Mac app IMHO. That said I never got into Storyboards on Mac. In Xcode 26.2 I can still create an AppKit project the "old way" which is New Project -> macOS -> App then change Interface to XIB then you get a project without a storyboard. If you want to go completely without Interface Builder you can but I don't think Apple ever had a template for that setup (well if they did I never noticed or it must have been a really long time ago). You can set the NSApplication delegate in main. #import <Cocoa/Cocoa.h> @interface AppDelegate : NSObject <NSApplicationDelegate> @property (strong) NSWindowController *mainWindowController; @end @implementation AppDelegate -(void)applicationDidFinishLaunching:(NSNotification*)aNotification { NSLog(@"Hello world!"); NSWindow *firstWindow = [[NSWindow alloc]initWithContentRect:NSMakeRect(50.0, 50.0, 400.0, 400.0) styleMask:NSWindowStyleMaskTitled backing:NSBackingStoreBuffered defer:NO]; firstWindow.title = @"Xibless"; self.mainWindowController = [[NSWindowController alloc]initWithWindow:firstWindow]; [self.mainWindowController showWindow:nil]; } @end // main.m int main(int argc, const char * argv[]) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; AppDelegate *appDelegate = [[AppDelegate alloc]init]; app.delegate = appDelegate; [app setActivationPolicy:NSApplicationActivationPolicyRegular]; [app run]; } } and I think you also need to build the menu bar programmatically. IMO there really is no reason to do all this. If you want to avoid Interface Builder I think it's more reasonable to just do the following: Create an Xib project. Keep the MainMenu.xib but inside it delete the window but leave the menu bar. Then in your AppDelegate just make your NSWindowController / NSWIndow in code. Then you're mostly without IB - enough for learning. Or if you want you can build the menu bar (see mainMenu property on NSApplication: https://developer.apple.com/documentation/appkit/nsapplication/mainmenu?language=objc).
Replies
Boosts
Views
Activity
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
Also CFURL is documented to have different behavior but CFURL and NSURL aren't they 'toll free bridged' so how does that work if you cast a CFURL to a NSURL? So I just did a dumb little test to answer this. I created a CFURLRef and read kCFURLIsHiddenKey and got false (as expected) so it would cache it. Then on another CFURL instance (that points to the same file) I did the same thing (so it was cache the value). After that I set hidden to YES: NSURL *toNSURL = (__bridge NSURL * _Nonnull)cfURL; [toNSURL setResourceValue:@(YES) forKey:NSURLIsHiddenKey error:nil]; Then back to the other instance I cast that one to another NSURL: NSURL *nsCastCopiedVersion = (__bridge NSURL * _Nonnull)aCopiedCFURL; And read isHidden and it is NO. Read aCopiedCFURL hidden and it is also NO. Then dispatch after dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [URLPrinter printCF:aCopiedCFURL]; [URLPrinter printNS:nsCastCopiedVersion]; }); And got: Print copied CF Not hidden // cached value - real value is true. Print copied NSCF: Hidden // hidden true value So indeed using CFURL instead would seem to avoid this. Learn something new every day. Now if I didn't already have a million lines of code already using NSURL I would just use CF instead (still might) because at least for my app I find dumping cache values at every run loop churn undesirable. I did have a better caching system implemented at some point but seems some of it got dumped it when I implemented a workaround to avoid -removeCacheResourceValue: crashes a couple of years ago. It'll all be back in biz soon. Thanks for the help guys.
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
When you access a property on the main thread, the system checks to see if the cached value is still valid, that is, has the main thread ‘turned’ between when you last got the property and now. I see. IMHO binding cache invalidation to the turning of a run loop while simultaneously recommending accessing -getResourceValue:forKey: on a background queue feels somewhat peculiar but I guess that peculiarity came during that long evolution. The main benefit of caching just until the run loop turns I guess would help if you were continuously calling -getResourceValue:forKey: in loop or in the middle of event handling but I wouldn't expect that to be so common given the recommendation to call -getResourceValue:forKey: off the main thread when possible. The downside with this short lived cache is that other threads can read stale values from -getResourceValue:forKey: calls unless they explicitly clear the cache using -removeCachedResourceValueForKey: etc. but using those methods wasn't always safe but hopefully they are now. I was working on just getting metadata I need with other APIs and caching them but there are some important resource values I need that seemingly are only available through the NSURL apis :)
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
So I've discovered if you create the NSURL on a background thread you can get stale resource values even on the next churn of the run loop. But whose run loop 'owns' the URL resources? The main thread's run loop ? The run loop of the thread the URL was created on? Or does NSURL do something like this: - (BOOL)getResourceValue:(out id _Nullable * _Nonnull)value forKey:(NSURLResourceKey)key error:(out NSError ** _Nullable)error API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)); { // do whatever to get the resource value //-- // schedule delete from cache. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(clearResourceValueForKey:) object:key]; [self performSelector:@selector(clearResourceValueForKey:) withObject:key afterDelay:0.0]; } I don't see how you can tie cached resource value state to a run loop - it doesn't make any sense to me, especially since the documentation advises doing file operations on a background thread/queue because hitting the disk can be slow. What if I'm sorting an array of NSURLs by some metadata on a background thread and the main thread run loop is just happily invalidating the cache resources behind my back? Maybe I'm not understanding something. IMO I think better behavior would be just to cache on first access and keep it until I explicitly invalidate it but I guess I have to use CFURL for that. I think it makes more sense to let the developer flush the cache in response to file coordination or whatever API being used to monitor the URL but I guess I have to build a cache on top of the cache.
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’26
Reply to NSURL - Are Cached Resource Values Really Automatically Removed After Each Pass Through the Run Loop?
Thanks for responding. I haven't yet been able to reproduce the issue in a small test project so either they made changes in a macOS update or there is some timing issue and/or way the NSURL is initialized in my real project teases the issue out. But I promise I got stale value for nonexistent NSURLIsHiddenKey until I started explicitly dumping it. In my real project the URL comes for -fileURLWithPath: (and initially created on a background thread). My real project is large and complex so when I have more time I'll have to see if I can isolate the issue in a small sample. Due the request by iOS and the server cache the user may see some discrepancies or additional nuances in how and caching behave, particularly regarding stale values. I'm on macOS. Explicit cache management is recommended, especially when dealing with URLs that may have changed state (e.g., deleted or modified), to ensure your application behaves predictably across different environments and runtime sessions. Also CFURL is documented to have different behavior but CFURL and NSURL aren't they 'toll free bridged' so how does that work if you cast a CFURL to a NSURL? I would certainly prefer explicit cache management. Chucking cached resource values at every churn of the run loop seems silly and IMO could cause unintended performance issues because the next time the app asks for the cache resource value I presume we hit the disk unnecessarily when nothing has changed. Chucking cached values at every churn of the run loop really reduces the benefits of caching in the first place - developers have to cache on top of the cache but you don't know what's cache? The only way to be sure you don't get a stale value is to call -removeCacheResourceValue methods, which again seems to reduce the benefits of NSURL caching in the first place. Also the problem with explicit cache management is I don't know if resource values are shared across NSURL instances. In the past I had a talk with an Apple badged person and I think he told me it was (or could be at that time but I'll have to check notes). At that time I discovered that calls to -removeResourceValueForKey and/or -removeAllCachedResourceValues could cause crashes. Do you know if each NSURL instance gets its own isolated cache or are they still shared by NSURLs that point to the same file (which I don't think would be safe)?
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’26
Reply to macOS Tahoe WKWebView - NSPrintOperation EXC_BREAKPOINT with Lots of Error Logging
Yes if I set the frame on printOp.view the EXC_BREAKPOINT issue is avoided. Otherwise the private WKPrintingView configured for the printOp has a frame of NSZeroRect.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jan ’26
Reply to How can I be notified if another app goes full screen on macOS?
If there is a way to get notified when another app goes full screen, I'm unaware of it. If it isn't appropriate for your status windows to ever be displayed in full screen mode have you tried using NSWindowCollectionBehaviorFullScreenNone on these windows? I have a window that should display in full screen sometimes, and like you I want to be polite and initially hide it. I've been using a hack forever to do this which mostly works but it isn't exactly pretty. It involves creating a hidden window with a certain collectionBehavior like NSWindowCollectionBehaviorFullScreenNone | NSWindowCollectionBehaviorCanJoinAllSpace and basically track if the active space contains this window. If it doesn't I assume the active space contains an app with a full screen window. Again not perfect but it's the best I could think of. If there is a better way to do it, I'd also like to know.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jan ’26
Reply to AppKit - Legal to Change a View's Frame in -viewDidLayout?
Thanks a lot for responding. Thanks for the post, it’s hard not seeing the code and how you're setting constrains in code. Would you be so kind to provide your code where you setting the constraints so developers here can see it? [..] it is generally not a good idea (and will lead to crashes) to directly modify the frame or bounds of a view that is managed by Auto Layout in my opinion. Initially I did not involve Autolayout at all explicitly. What I had was a small container view controller with something like this (no explicit constraints): @implementation SmallInfoWrapperViewController -(void)viewDidLayout { [super viewDidLayout]; NSRect bounds = self.view.bounds; CGFloat lineHeight = 1.0; self.separator.frame = NSMakeRect(0.0,bounds.size.height-lineHeight,bounds.size.width,lineHeight); BOOL separatorVisible = !self.separator.isHidden; CGFloat wrappedViewHeight = bounds.size.height; if (separatorVisible) { wrappedViewHeight -= lineHeight; } self.wrappedView.frame = NSMakeRect(0.0,0.0,bounds.size.width, wrappedViewHeight); } @end That was fine when wrappedView was an NSScrollView (which contains an NSOutlineView). The NSScrollView/OutlineView/Clipview triplet comes out of a xib which is many years old that also has no explicit Autolayout constraints. All worked fine. Once wrappedView became an NSGlassEffectView (which now contains the scroll view) that is when Autolayout said it needed to break constraints the system was creating from autoresizing masks and it listed weird fixed width and height constraints. I find Autolayout useful but avoided it in certain situations where it seems unnecessary it could overcomplicate and the task was so easy (like this one) it felt like cutting a stick of butter with a chainsaw. But the system seems to be trying to make Autolayout somewhat of a requirement so rather than try to fight it I just gave in. self.wrappedView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[leading, trailing, bottom, top]]; But I initially forgot to remove self.wrappedView.frame from -viewDidLayout which is when I hit the exception. Fix is to instead modify the constant of the top constraint when separator.isHidden changes instead. So I already knew what caused the issue and how to fix it but the exception: "The window has been marked as needing another Layout Window pass, but it has already had more Layout Window passes than there are views in the window" did make me curious enough to ask this question because it doesn't seem so uncommon/unreasonable to make adjustments in -layout and -viewDidLayout. Something like: -(void)layout { [super layout]; [self.dateLabel sizeToFit]; if (![self doesDateLabelFitAtNaturalWidth]) { [self useShorterDateStyleLayout]; } } Of course the above is just "concept code" but shrinking a control based on available space in certain situations is more straightforward and easier to maintain in manual layout than with Autolayout. Most of the time Autolayout is preferred, I agree. In any case it doesn't feel appropriate for the system to generate width and height constraints from autoresizing masks ever (perhaps I have a naive point of view but that looks like it could cause some real trouble to me). IMO it makes sense to generate leading, trailing, top and bottom constraints but width/height I'm not sure about that. There was like some weird 250 point min width constraint or something and I have no idea how that possibly could have been calculated from autoresizing masks. In another area I had to fix I also ran into a min width constraint conflict when I downsized a window width because the generated constraint from an autoresizing mask somehow created a weird min width 50 constraint that was too big for the really small window size. Overall it now seems somewhat dicey to set frames in -viewDidLayout / layout overrides because even if you aren't using constraints explicitly it is difficult to determine what the system is generating under the covers. What do you mean by legal? What I mean by legal is safe to modify and supported. In my opinion I think there should be a point (like UIKit -viewDidLayoutSubviews) where layout can be safely modified with or without explicit Autolayout constraints to give developers maximum control (even though rarely needed). I don't really understand why the system doesn't permit a more hands off approach like this: self.lockLayoutInvalidation = YES; [self doAutolayoutOnSubTree]; [self callViewDidLayout]; self.lockLayoutInvalidation = NO; Whatever the layout is after viewDidLayout - it is what it is. Any overlapping views or mistakes or whatever leave it on the developer to find and fix but crashing, throwing, etc. seems a bit much.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jan ’26
Reply to macOS Tahoe WKWebView - NSPrintOperation EXC_BREAKPOINT with Lots of Error Logging
Thanks for replying. Sure. NSPrintOperation *printOp = [self.webView printOperationWithPrintInfo:[NSPrintInfo sharedPrintInfo]]; if (printOp == nil) { os_log_fault(OS_LOG_DEFAULT, "Nil print operation."); return; } if (self.view.window != nil) { [printOp runOperationModalForWindow:self.view.window delegate:self didRunSelector:@selector(myPrintOperationDidRun:success:contextInfo:) contextInfo:nil]; }
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jan ’26