Difference between NSView and NSViewController - macos

What's the difference between NSView and NSViewController is XCode 4 Cocoa application?

NSView is just the view in MVC. NSViewController has a NSView (or a subclass of NSView), and also contains the code for the controller in the MVC model.
I may be wrong, since I'm drawing the answer from my experience with iOS, but I think it should be about the same for OSX.

Related

Click in view of NSCollectionViewItem

I'm new to Cocoa dev, so many concepts of it are not clear to me...
I'm trying to build a simple app which will use Flickr API to retrieve user photosets and show them in a NSCollectionView, by clicking them, will start to download the photos of the photo set.
I'm using Xcode 5.0.1 with latest SDK which is 10.9
After reading some articles about how to use binding to deal with NSCollectionView, I'm now facing another problem regarding handling events in NSCollectionViewItem.
Per I understanding, mouse events can be easily handled by implement
-(void) mouseDown:(NSEvent *)theEvent
In a NSView subclass, say
#interface MyViewController : NSView {
}
And assign the view custom class to the subclass I made (MyViewController) in InterfaceBuilder.
Now, I have no problem to do as above, and the mousedown did handled as expect in most of widgets.
The problem is, I have a NSCollectionViewItem subclass as below:
#interface MyItemController : NSCollectionViewItem {
}
I'm trying to implement mousedown method there, this class was set to as File's Owner in a separated nib file. And the view will be automatically load when the NSCollectionView loaded.
Now, MyItemController cannot be as customer class in the view object in IB which is obviously because of it is not a NSView subclass but a NSCollectionViewItem subclass.
If I write a subclass of NSView and make the custom class of view object, I can get the mousedown.
However, I cannot get the representedObject and index of NSMutableArray in this approach and they are the essential information I need.
So my question is, what is the right way to deal with mouse events view of NSCollectionViewItem?
My code in GitHub here:
https://github.com/jasonlu/flickerBackupTool
Thanks!
UPDATE
I found a approach to solve this problem is by subclassing NSView and implement mousedown and use super, subviews to get and index and the array itself
- (void)mouseDown:(NSEvent *)theEvent {
NSCollectionView *myCollectionView = (NSCollectionView *)[self superview];
NSInteger index = [[myCollectionView subviews] indexOfObject:self];
NSLog(#"collection view super view: %#",myCollectionView);
NSLog(#"collection index: %ld",index);
NSLog(#"array: %#", [[myCollectionView content] objectAtIndex:index]);
}
It seems work, but I'm not sue if this is the best practice, it looks like depends on view too much and took a long way to reach the array.
I wouldn't bet that NSCollectionView always creates all subviews (subviews which are far away from the viewing area might be delayed and/or reused). Therefore, I wouldn't rely upon subview searching.
Overload NSViewController to create an NSView so that the representedObject assigned to the NSViewController is accessible from the NSView. From there you could search the actual content for index determination.
Overloading NSCollectionView and recording the actual index during view creation would probably not work well because a deleted item probably doesNot re-create any views.

NSView subclass with IBOutlets and IBActions

I have an NSView subclass that is used for displaying a custom object. The drawing logic is all in methods on the subclass. There is no view controller associated with this view.
I have added a couple of controls next to this view in Interface Builder that will be used to control the display of the object.
Is it OK to have these controls connected to IBOutlets and IBActions on the view? I know that it's possible, but is it poor design? Should I be using an NSViewController?
No that is completely fine and it's how things are supposed to connect together. There is no need to use an NSViewController as it only really helps manage the creation of the view from a .nib file and it can still only manage one view.

How to programmatically subclass a UIViewController stored in a Storyboard?

I'm working on my first iPad application and using Storyboards for the first time.
I've got UITableViewController in my Storyboard that uses "Dynamic Prototypes" for custom cells.
What I want to do is programatically instantiate my UITableViewController subclasses but loading the super view controller from the Storyboard.
This is because I have a single UI but multiple subclasses for specific functionality that I need for each different instance.
This was very easy to do with .xib files, I would write the following code:
MyViewControllerSubClassA *viewControllerA = [[MyViewControllerSubClassA alloc] initWithNibName:#"generalViewControllerNib" bundle:nil];
MyViewControllerSubClassB *viewControllerB = [[MyViewControllerSubClassB alloc] initWithNibName:#"generalViewControllerNib" bundle:nil];
I know I can assign a subclass in the Storyboard editor when clicking on the View Controller but I want to set the subclass programmatically when instantiating.
This seems impossible to do with Storyboards as they are instantiated automatically.
This makes the entire concept of Storyboards seem flawed and not very OO.
If I move the View Controller out of the Storyboard and into a .xib file I lose the ability to use Dynamic & Static Prototypes cells as these are supported only when using Storyboards. Also Apple's documentation basically says use Storybaords from now on.
I would try something like this:
MyViewControllerSubclassA *controllerA = (MyViewControllerSubclassA *)[self.storyboard instantiateViewControllerWithIdentifier:#"myGenericVC"];

How to refer to Cocoa controls located in in the same NSWindow?

I have a NSWindow with an NSView and an NSTextField inside.
I'm using Interface builder right now. I have dropped the two controls on the default NSWindow and subclassed an NSView. I'm implementing the -drawRect method from NSView and I need to access to the content of NSTextField.
How do I refer to the instance of NSTextField from a method inside the NSView ?
Your NSWindow is (or should be) controlled by a window controller. In IB you create an outlet for the NSTextField in your window controller. Using the outlet, you can then refer to the NSTextField:
In your window controller .h file:
#property (strong) IBOutlet NSTextField *myTextField;
In your window controller .m file:
#synthesize myTextField;
From there you can in your controller:
[[self myTextField] setEditable: NO];
A point to note is that you do not access the controls in a window directly from that window as windows (and all Cocoa controls for that matter) are statically stored in a XIB/NIB file. All access to controls (UI elements) is channelled through controllers (NSWindowController, NSViewController) which in turn are capable of loading XIB/NIB files.
Apple provides various samples in their docs on how to do this.

point of UIViewController in IB

What exactly is the point of adding a UIViewController in IB? There is no way to add code like you can if you create a viewController in Xcode? And if you can what is the advantage of doing it in IB.
And isn't the whole point of a MVC to seperate code into "modular" parts so why would add a ViewController in IB
Sometimes all you need is a UIViewController. But most times you would create a UIViewController subclass of your own (in IB).

Resources