How come UIKit doesn't have UIMatrix, UIButtonCell class like AppKit's NSMatrix, NSButtonCell? - uikit

I find AppKit's NSMatrix and NSButtonCell classes useful for grids of buttons. I wonder why Apple never created these counterparts for UIKit?

The equivalent in iOS is UICollectionView. It's much more flexible and useful than NSMatrix, here is a tutorial.

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.

What is a standard way to add a ViewController in a Mac OS X Cocoa app? (or is it required?)

I'd like to start a Cocoa app with a ViewController just like the iOS "Single View App" template, but there is no such template (is there a public / open source one that can be used?)
Is it true that for Cocoa apps, we don't really need one, because an NSView can do everything already? We can just put all the event handling in our custom NSView class. Could it be that iOS requires it a lot more because rotation is handled by the ViewController and rotation is usually required? But if we use MVC, then it might be better to always use a ViewController, and if so, is there a standard way, a template, to do it?
The "Controller" in OS X with respect to managing NSViews is the NSWindowController. Though Drummer says that NSViewController isn't very useful, I must disagree - it is useful for splitting up your NSWindowController once it gets too large, and has clear logical divisions in terms of views.
You could have one NSWindowController, and once it gets complicated enough, the NSWindowController could delegate tasks corresponding to specific views to subclasses of NSViewController, and in that respect it is very useful.
In the default templates (if I remember correctly) the AppDelegate takes the role of the window controller, though it isn't technically one. In more complex applications it is a good idea to instantiate a window controller instead.
As long as you don't mix up the controller and view anything can be used. The View should be relegated to just display and basic input handling.
On OS X NSViewController isn't as often used as UIViewController on iOS. One of the reasons is that it's not really useful and lacks a lot of the nice features of UIViewController. There are only a couple of situations where you really have to use them, like when using an NSPopover.
There are several ways to structure your OS X code. One of them is using NSWindowController. You can think of NSWindowController as the equivalent of UIViewController on iOS.

Creating gradient button bar in cocoa

My question is almost exactly the same as this question, however the answer accepted (and only) answer was to use BWToolkit which is no longer an option for me because it isn't compatible with Xcode 4.
How can I create a similar bar in interface builder or programmatically, without BWToolkit?
You can look at the source code of BWToolkit. It uses a custom NSView subclass to do the drawing. Cocoa hasn't got a built-in control for this.
Alternatively, you can use BWToolkit, but just the parts you need (BWAnchoredButtonBar, BWSplitView, BWAnchoredButtonBar and the NSColor and NSView categories). You don't need to include the entire framework in your app.

Cocoa forControlEvents:WHATGOESHERE

In Cocoa/Objective-C if I have created a button programmatically, what do I put in for my control event?
[btnMakeChar addTarget:self action:#selector(makeChar:) forControlEvents:WHAT GOES HERE?];
In iOS you can write it like so forControlEvents: UIControlEventTouchUpInside
I can't find anything to show what I would use for just cocoa, not cocoa touch
I'm not sure if I understand you correctly, but if you're programming a Mac,
[theHappyButton setTarget:self];
[theHappyButton setAction:#selector(doStuff)];
it is two separate lines, rather than the one combined line of code on an iPhone.
I hope that is what you were after??
To find it in the doco: choose on the 10.6 doco (not iOS) and search on "setAction:". You'll see it in NSControl Class Reference. NSButton is of course a subclass of NSControl.
The method you're asking about does not exist in Cocoa, so nothing goes there. Cocoa controls have a single target with a single action, and either use a different addTarget:-type method for each kind of action or expect a delegate object that will handle all the events they generate.

DrawRect on the iPhone vs. the Mac

I am an experienced iPhone dev beginning to work on my first Mac app. One thing that is really throwing me off is the differences between UIView and NSView. It seems that I cannot set the background color of a NSView via interface builder as I can with a UIView. It also seems that I cannot do it by simply sending a setBackgroundColor: message to it. All the examples I have seen are overriding drawRect: in a subclass of NSView. Is that really the only way to do it? What is the conceptual difference here, and why is it this way? NOTE: I am only trying to set the background color to the default grey.
Re: Alex's answer:
It's not just that it's older; or rather;… It isn't that it's older. The fact of the matter is that UIKit is simpler. UIView is a much less general construct than NSView; the general method that Apple is pushing for content-rich applications on the iPhone is using OpenGL or Core Animation, relegating UIView, by and large, to simple container stuff. In this context, setBackgroundColor: is useful.
On the Mac, on the other hand, NSView is a highly generic interface element, and for most uses, setBackgroundColor: would just be plain unnecessary. 9 out of 10 times, if you're on a Mac and changing the background color this is either because you are preparing to do your own drawing of user interface elements, or you are doing something that is most likely not condoned by the AHIG.
In summary:
There is no way apart from subclassing it. (NSView is made for subclassing, UIView is made for drop-in-and-use.)
Remember that AppKit is much, much older than UIKit — like 20 years older. Many features you'd consider basic and essential just aren't present in AppKit.
So the answer is yes: if you want to draw a colored background on an NSView subclass, you will need to override drawRect:. NSRectFill makes it easy to do this.

Resources