How to implement a DataView in Cocoa? - xcode

What would be the best way to implement (using Cocoa) a DataView as presented in this example:

1. IKImageBrowserView
The image below is taken directly from Apple's Image Kit documentation and does exactly what you need.
2. NSCollectionView
NSCollectionView is more general because you are not restricted to just presenting images; you can present a collection of any NSView subclass you like. Try this if you need more customisation. For example, you could have a NSImageView, NSTextField and NSButton in your subclass if you needed to have a more complex user interface.

Related

Should You Still Subclass NSControl in 2018

As of 2018, what is the correct way to create a custom control with AppKit/Cocoa?
The traditional technique has been to subclass NSControl and/or NSCell for the type of custom control you're implementing. (Such as an NSButton that does custom drawing.)
However, in WWDC 2014-204 Apple stated that NSCell is on its way to "Formal Deprecation". In WWDC 2012-217, Apple suggests subclassing NSView and taking advantage of layer-backing and layer properties to draw a simple button.
If you subclass NSView to create a custom control (such as a "better button") then you lose a lot of functionality that NSControl offers, such as pre-wired action and target properties, mouse-tracking, keyboard activation and probably a bunch of other things I'm not even aware of.
If you subclass NSControl, or even NSButton, what is the correct way to take over all of the drawing? Apple's Programming Guide has not been updated regarding this. In particular, can an NSButton subclass just override all the draw... methods from itself and NSCell and then just do what it wants to do in updateLayer? Is there any guarantee that the existing NSButton/NSButtonCell drawing code won't still do any drawing?
What if you wanted to build a button with a custom background but still uses a string-based title or attributedTitle? NSButton offers this but how does the title drawing interact with updateLayer?
My use-case is to create a custom button that offer more visual states and more visual designs than a traditional NSButton. Using a layer-backed NSView and updateLayer makes implementing all of the different states a breeze, but I'd prefer to subclass NSControl or even NSButton so that I also retain all of the functionality that those classes already offer.
Edit 1: Changed wording based on comments below to more accurately reflect the current deprecation state of NSCell.

Does Interface Builder's new IBDesignable attribute work with NSButton and other controls in Cocoa?

I have managed to get the IBDesignable/IBInspectable attributes working with direct subclasses of NSView but not with a direct subclass of NSButton. This is causing me to question if in fact the Cocoa implementation is somehow limited to NSView only.
Almost every example on the web (and Apple WWDC 2014 Xcode video) use NSView and then drag a custom view component from the library onto the canvas (and then change its class).
Is it possible to use IBDesignable with subclasses of NSControl and NSButton etc...? I have seen many examples on the web using UIButton.
If it is possible, then what are you supposed to drag from the library onto the canvas? It doesn't make sense for it to be a "custom view". On the other hand, there is no "custom control" available.
To be clear, I can get the IBInspectable attribute to show up at design time; but any changes don't seem to live render at design time.
The workaround is to wrap any custom NSButton I want to create within an NSView (via composition) but this seems like a bit of a hack...
I started playing around with a custom NSButton and NSButtonCell.
Dragging a button from the library onto the canvas and changing its class and the cell class doesn't live render. I think this is because Interface Builder still does a lot of custom things to setup NSButtonCell.
What works fine for me is dragging a custom view from the library onto the canvas and set its class. For this to work you need to setup the cell inside NSButtons -initWithCoder:.
Also I found a sample from Apple with a layer-backed custom Checkbox.
You need to drag an NSButton onto the view, then set the Custom Class to your specific NSButton descendant. Not sure why it doesn't work when you start with an NSView.
What can give you a hint is that the NSButton specific attributes aren't in the "Attributes Inspector". Hence there must be some setup at the time you drag the control onto the view.

Cocoa Programming: Adding a Rectangle to a Custom View (NSView)

Is there a simple way to add a simple rectangle to a Custom View without using a custom NSView subclass for it? Something along the lines of:
Assign an IBOutlet (let's call it colorWheelView) of NSView type to the CustomView
In my NSViewController's initWithNibName use it to change draw the rectangle:
// pseudocode
self.colorWheelView.addRectangle(myRectangle);
self.redraw()
The only way I've seen it done (on this site, and in my book Cocoa Programming for Mac OSX, pp. 241) is by making a custom class for the Custom View and modifying its drawRect method... Is this really the only way to accomplish this?
Edit: not sure why formatting is not being rendered correctly. I'm trying to fix it.
It really isn't all that hard to roll your own..
Just add an NSArray property to your NSView subclass, then in your drawRect method draw them either manually or using one of the NSRectFillList* methods provided by AppKit already.
(Beware: those take a plain C array, not an NSArray).
You wouldn't want to manually trigger the redraw from outside the view as in your sample code, though. To keep things consistent your addRectangle would trigger a redraw of the view itself e.g. by calling setNeedsDisplay:.

Is it possible to design NSTableView cells using Interface Builder? (not for iOS apps)

Is it possible to design NSTableView cells using Interface Builder?
I know this is actually possible if your project is for iOS but somehow IB does not render the cell container if its for Mac OS X.
Im not sure if Amy gave that answer when this couldn't be done before, but this can be done quite easily on interface builder.
It can be done using view-based table view cells (instead of cell based) shown in the apple docs. There's is even a decent example you can download from the reference site.
No. The reason it's possible on iOS is because UITableViewCells inherit from UIView. Interface Builder lets you lay out views by putting other views within them.
On the desktop, for performance reasons from back when NextStep ran on 16mhz computers, NSCell does not inherit from NSView. A cell, on the Mac, does not have its own coordinate system or subview hierarchy, so it doesn't make sense to edit it in Interface Builder: you couldn't put other views within it!
So to make a custom cell, you need to draw everything with drawing functions such as CoreGraphics. You can't just drop in an NSImageView, you have to draw the image directly.

buttons in interface buider

has anyone an idea if it is possible to create ellipse or polygon buttons in IB?
Directly, not without a library.
You can, however, create an NSView subclass which performs your shape drawing for you. You will need to implement the mouse events to perform clicks correctly. Drop an NSView on your window, set its class in the inspector to your custom-drawn NSView subclass, and you're set. Check out this tutorial.
You could also create a custom control, derived from NSControl. Check out this documentation.

Resources