Skip to content

Instantly share code, notes, and snippets.

@jwilling
Last active March 5, 2023 22:01
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jwilling/4186817 to your computer and use it in GitHub Desktop.
Save jwilling/4186817 to your computer and use it in GitHub Desktop.
Lets help improve AppKit.

Is AppKit causing you frustration? Instead of just complaining about it, lets try to make it better by compiling a list of specific problems with AppKit. Leave a comment below, and I'll include it in the list.


##NSView##

  • NSView does not have the ability to set an affine transform (rdar://15608609)
  • Controls that have cells (such as NSTextField) do not respond properly when layer-backed. Take NSButton as an example. When not layer-backed, it will animate properly using the animator proxy. When layer-backed, using the animator proxy breaks focus rings (they jump to destination immediately). Currently, directly manipulating the layer of a cell-based control is not supported (and will lead to a broken interface), but is much needed. (rdar://15608822)

##NSViewController##

  • NSViewController could be more useful. It has -loadView but no other lifecycle methods. (rdar://15608948)

##NSClipView##

  • NSClipView has performance issues. Improved under 10.9.
  • NSClipView has a poor animation when using -scrollRectToVisible:. (rdar://15609175)

##NSTableView##

  • NSTableView has odd animation artifacts when scrolling with the keyboard with a fast key repeat.
    • Due to the clip view issue mentioned above. (rdar://15609175)
  • NSTableView does not fully support sections – all rows in the table are numbered sequentially, rather than as (section #, row #) as UITableView does. This makes it difficult to alter sections independently. (rdar://15609306)

##NSCollectionView##

  • NSCollectionView is not performant. It loads every single cell all at once, and it keeps them all in memory. It does not reuse cells. (rdar://15609666)

##NSBrowser##

  • NSBrowser is not view-based like NSTableView and NSOutlineView.

##NSSlider##

  • NSSlider requires use of private method -_usesCustomTrackImage in order to completely customize appearance.
  • NSSlider needs a "rounded textured" style for use in window frames (like in Finder).

##NSSearchField##

  • NSSearchField does not support tokens.

##NSTextField##

  • NSTextField does not support a custom context menu when the text is selectable and/or editable. It requires hacking around with the field editor to implement this functionality.

##NSSplitView##

  • NSSplitView makes simple customization like setting priorities and min/max sizes for views is unnecessarily complex.

##NSProgressIndicator##

  • NSProgressIndicator still draws the original progress bar even if drawing is overridden. (rdar://15609817)
  • NSProgressIndicator's color cannot be changed without workarounds such as Core Image filters. (rdar://15609817)

##NSPopover##

  • NSPopover does not offer a way to customize its appearance apart from the two default styles.
  • NSPopover steals keyboard focus.

##NSWindow##

  • NSWindow animation is poor without the use of some not-so-nice hacks.
  • Borderless NSWindows (NSBorderlessWindowMask) do not have the ability to round their corners.
  • Borderless NSWindows with a layer-backed content view do not get a shadow.
  • NSWindow is really difficult to customize.

##NSDocument##

  • NSDocument has very bad support for documents that aren't fully loaded into memory. Nearly all of the API assumes that you can generate a singular NSData object to store your document in, which isn't true if half of your document is on disk only and the other half in memory only.
  • NSPersistentDocument doesn't support file wrappers (bundles), even though that's a requirement for the sqlite data storage with sandboxing enabled. All workarounds at this point are huge hacks.

##NSObjectController##

  • While NSObjectController and its subclasses (e.g. NSArrayController) support retrieving objects from a Core Data managed object context, they do not offer a way to receive per-change notifications. This means that you need to reload your entire view vs. inserting/removing/moving the cells that were updated. Ideally, we would want a port of NSFetchedResultsController.

##NSDrawer##

  • NSDrawer should either be deprecated or have its API fully updated to support customization.

##NSImage##

  • NSImage does not support drawing stretchable images with caps.

##Field Editors##

  • Field editors are conceptually unusual and confusing.

##Cells & Controls##

  • The use of cells in specific controls such as NSTextField and NSButton make them difficult to customize.
  • NSButtonCell is poorly thought out. bezelStyle, gradientType, buttonType, isHighlighted, state and a few more make for a really really confusing subclassing experience.
  • NSTextFieldCell does not have vertically-centered text. A subclass is required.
  • Template images and window-style engraved text should be useable without the use of captive cells.
  • AppKit controls need image-based customization properties like their UIKit counterparts.
  • AppKit does not provide HUD-styled controls.
  • Interface Builder does not support bindings for custom controls.

##Misc. (not necessarily AppKit)###

  • There is no Cocoa wrapper for the Carbon hotkeys API.
  • There is no Cocoa wrapper for FSEvents. The Spotlight stuff doesn't really work for sandboxed Applications.
  • There is no API for AirPlay.
@indragiek
Copy link

A couple more minor to add:

  • NSBrowser has not been updated to be view based like NSTableView and NSOutlineView
  • NSSplitView has a very difficult to use API. Simple things like setting priorities and min/max sizes for views is unnecessarily complex.
  • AppKit provides an HUD window panel but no HUD styled controls. (Attempting to fix this with SNRHUDKit)
  • NSSlider's drawing is impossible to customize without overriding a private method (- (BOOL)_usesCustomTrackImage). Without this override, it'll draw the default bar regardless of how you override the drawing methods.
  • NSProgressIndicator also draws the default progress bar even if you override the drawing in a subclass.
  • NSTextFieldCell's text isn't vertically centered. It requires a subclass like this to get that working properly.
  • You can't set up custom bindings to controls from Interface Builder.

@jeremytregunna
Copy link

@indragiek Thanks. I'm already using my own custom NSViewController subclass which gives me the flexibility I've come to expect from UIViewController.

@justinkao
Copy link

  • NSPopover steals keyboard focus and there's no good way to prevent it.
  • NSSearchField doesn't have a tokenizing option.
  • For that matter, I would really like to add button-like widgets to arbitrary NSTextFields, as in my browser's location bar.

@justinkao
Copy link

  • Nevermind HUD-styling, I would settle for a window-frame-suitable (i.e. "rounded textured") NSSlider. Finder has one. iPhoto has a different one. iTunes has a third. AppKit doesn't have any. Aaargggh.
  • NSDrawer badly needs some Lion love.
  • The proliferation of third-party preference window controllers, hotkey-capturing controls, and popover windows probably indicates something.
  • Methods to draw the window frame engraved text effect/template image effects in code without having to fool around with captive cells.

@justinkao
Copy link

  • Real support for sections in NSTableView

@jwilling
Copy link
Author

jwilling commented Dec 2, 2012

Also thought of another: NSView methods for rotation about points and such could be made much simpler with the addition of a setTransform: method, taking a CGAffineTransform.

@jwilling
Copy link
Author

jwilling commented Dec 2, 2012

@nasturtiumlabs What part of NSDrawer needs love? The appearance, or the API? Also, can you clarify your problems with NSTableView sections?

@pieteromvlee
Copy link

  • NSButtonCell is an abomination; bezelStyle, gradientType, buttonType, isHighlighted, state and a few more make for a really really confusing subclassing experience
  • Core-Image really feels hacked on top of the traditional NSView hierarchy

Has been mentioned already, but:

  • NSSplitView is a maze of confusing method calls
  • NSWindow customisation is a pain
  • `

@anlumo
Copy link

anlumo commented Dec 2, 2012

  • Activating layer-backed views means that the drawing code of the regular cocoa controls goes nuts. Has been true from when this feature was introduced, and has since been "fixed" in every major release of Mac OS X. If iOS can work fully layer-backed, why can't Mac OS X?
  • Something like the iOS Storyboards aren't possible on Mac OS X, because there is no support whatsoever for the application workflow on Mac OS X (related: NSViewController issue). This means that you have to spend a lot of time with window management when you could be doing business logic and features.
  • NSDocument has very bad support for documents that aren't fully loaded into memory. Nearly all of the API assumes that you can generate a singular NSData object to store your document in, which isn't true if half of your document is on disk only and the other half in memory only.
  • NSPersistentDocument doesn't support file wrappers (bundles), even though that's a requirement for the sqlite data storage with sandboxing enabled. All workarounds I've encountered are major hacks that don't work properly.
  • There is no Cocoa wrapper for FSEvents. The Spotlight stuff doesn't really work for sandboxed Applications.
  • There is no hotkeys API other than the Carbon one.

@jwilling
Copy link
Author

jwilling commented Dec 2, 2012

NSWindow customisation is a pain

That reminds me:

  • Borderless windows (NSBorderlessWindowMask) do not have the ability to round their corners
  • Borderless windows with a layer-backed content view do not get a shadow

@jwilling
Copy link
Author

jwilling commented Dec 2, 2012

NSPopover steals keyboard focus and there's no good way to prevent it.

Also:

  • There is no way to customize the appearance of a NSPopover, apart from the two default styles.

@jwilling
Copy link
Author

jwilling commented Dec 2, 2012

  • NSProgressIndicator color cannot be changed without workarounds such as Core Image filters.

@justinkao
Copy link

@jwilling NSDrawer: The appearance doesn't match Lion, it's still in the brushed metal age. NSTableView doesn't have true sections as UITableView does, it has group rows -- all rows in the table are numbers sequentially, rather than as (section #, row #) as UITableView does. This makes it difficult to alter sections independently, among other things.

@indragiek
Copy link

More:

  • While NSObjectController and its subclasses (e.g. NSArrayController) support retrieving objects from a Core Data managed object context, they do not offer a way to receive per-change notifications. This means that you need to reload your entire view vs. inserting/removing/moving the cells that were updated. Ideally, we would want a port of NSFetchedResultsController.
  • NSImage does not support drawing stretchable images with caps. (RBLResizableImage) adds this functionality).
  • NSTextField doesn't support a custom context menu when the text is selectable and/or editable. It requires hacking around with the field editor to implement this functionality.
  • There is no way of registering to receive NSEvents for the media keys. This currently requires using an event tap like SPMediaKeyTap, and event taps don't work in the sandbox.
  • AppKit has no shortcut/global hotkey APIs equivalent to Carbon

@indragiek
Copy link

  • No AirPlay APIs whatsoever on OS X (not even an AirPlay compatible movie player component like iOS)
  • No APIs to access common media sources like iPhoto and iTunes. iOS has great APIs for both. We have to resort to parsing XML.

@indragiek
Copy link

@jwilling
Copy link
Author

jwilling commented Dec 3, 2012

It requires hacking around with the field editor to implement this functionality.

I'll also add to this that field editors are somewhat odd and excessively complicated.

@dannygreg
Copy link

There is no Cocoa wrapper for the Carbon hotkeys API.

I fixed this in DGGHotKey.

@jwilling
Copy link
Author

jwilling commented Dec 4, 2012

@dannygreg Thanks, I'll add that.

@indragiek
Copy link

If the Core Data issue has been resolved in 10.8, then I don't think there's anything to complain about. This is for changes to make to AppKit going forward (and speaking of which, Core Data is a separate framework altogether). Regarding NSAnimation, this was a class that was used pre-Core Animation, and Core Animation has more than replaced the functionality of NSAnimation. There's nothing to do to NSAnimation except perhaps deprecate it.

@indragiek
Copy link

(last comment was in reply to @CodaFi).

@avaidyam
Copy link

avaidyam commented Dec 6, 2012

SCEvents is a good Cocoa wrapper for FSEvents.

@jwilling
Copy link
Author

jwilling commented Dec 6, 2012

Almost forgot:

  • NSView does not have a way to set the background color without subclassing or setting the layer's background color.

@jwilling
Copy link
Author

jwilling commented Dec 6, 2012

  • NSBezierPath cannot provide a Core Graphics representation of the path (CGPath), nor can it be initialized with one.

@jspahrsummers
Copy link

NSAnimation should be deprecated immediately in favor of Core Animation.

@CodaFi @indragiek This isn't tenable with current APIs, since NSAnimations are the only way to animate windows right now.

@uchuugaka
Copy link

also NSAnimation is the only way to animate controls that do not provide access to their components, like NSSlider's knob.

@corbinstreehouse
Copy link

Hi all,
For this to be really useful you should relate the Apple provided "radar numbers" for each issue, so it is officially logged with Apple and the appropriate AppKit engineers are aware of the issue.

@jwilling
Copy link
Author

jwilling commented Dec 6, 2013

@corbinstreehouse Sorry, I never received a notification for your comment. I'm not sure how many of these are filed as radars, but when I get a chance I'll run through again on 10.9 and file any of the ones that remain as unfixed and update with the radar numbers.

@CodaFi
Copy link

CodaFi commented Apr 20, 2014

  • Things that still cannot have weak references despite (ideally) having trivial backing variables:
Class Ideal Backing Reason Radar
NSATSTypesetter CTTypesetterRef Instances are cached internally -
NSColorSpace CGColorSpaceRef Instances are basically immortal rdar://16669956
NSFont CTFontRef Manually controls its own retain count rdar://16669960
NSParagraphStyle CTParagraphStyleRef Manually controls its own retain count (is actually one of its flags) rdar://16669966
NSMutableParagraphStyle (See Above) (See Above) rdar://16669966
NSTextView None Goes to great pains to manually manage its own retain count -
  • NSParagraphStyle should not have a mutable subclass. It should have immutable mutator methods that generate copies (rdar://16669988).
  • NSPasteboard does not send notifications for changes, nor does it have any means of observing changes in what is posted from any end of the pipe (rdar://16669974).
  • CFPasteboard has been around a long time, yet still hasn't been made public (rdar://16602986).
  • Layer-hosting DockTile and Status Bar custom views do not draw (rdar://16534607).
  • The command panel for NSSpeech[Recognizer/Synthesizer] is not public, and still hidden in Carbon (rdar://16670002).
  • There's still no UIDevice-like class despite there being a well-maintained Machine Attributes plist backing the About This Mac panel (rdar://16670004).
  • NSSound uses either the deprecated parts of AudioToolbox, or the deprecated parts of CoreAudio. Either way, it's pretty crufty up in there. Needs some OpenAL love (rdar://16670028)
  • So much of CGL is deprecated, it's basically useless.
  • NSCursor does not expose diagonal cursors (rdar://16695476), however they are a part of the JDK.
  • NSScreen does not bow to object equality (rdar://16737571)
  • NSRunningApplications hash to 0, meaning they really don't like being put in NSSets.
  • NSPrintInfo exposes an NSMutableDictionary.

@konstantinpavlikhin
Copy link

Ideally, we would want a port of NSFetchedResultsController

Have a look at KSPFetchedResultsController.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment