I'm an iOS developer just starting to develop for OS X. In iOS, I always follow the MVC pattern, and put appropriate code in UIViewController subclasses. The App Delegate simply initializes the main view controller, and that's it. After that the view controllers handle all logic.
But in OS X, I seem to put everything in the app delegate. My app delegate class is now about 300 lines long and I am wondering how I can follow the same pattern I did in iOS. There are no view controllers!
What I mean is, what is the common accepted way to organize code for Mac Application?
You can create your own controller classes, and put an instantiation of these controller classes between the app delegate or model objects, and your view objects. Just because there is no pre-built view controller class, does not mean that you can't make your own similar partition, by creating custom controller classes of your own, as needed.
Related
I have studying how to use IKImageView in my app. I downloaded the following demo from Apple site.
https://developer.apple.com/library/mac/samplecode/IKImageViewDemo/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004049
One thing I do not understand is: This project has only implemented a Controller class.
#interface Controller : NSObject
{
...
I do not understand how does it work at all. If I create a new project in XCode, it will usually generate an AppDelegate class which implements NSApplicationDelegate interface.
I do not know if I understand the mechanism correctly.
Does the following steps describe how it works?
1) In info.plist it specifies the main bundle is MainMenu.xib.
2) the Window is binded to the Controller like so
3) When the application starts, it loads the Windows from the MainMenu.xib and the Controller class takes over the windows interaction from there.
It's really old sample code. It predates Xcode project templates generating an app delegate for you.
Back then, early Xcode and ProjectBuilder (the old name for it)
Left it up to you to do that.
Lots of older sample code has this sort of thing. As long as things get kickstarted by nib loading, magic happens, objects are instantiated and connected
If you have a simple controller that inherits from NSObject and it has a proxy in you main nib file, it will get created. If you also connect its proxy as delegate to some view or control in the nib, all of that happens.
You don't technically need an object that is the delegate of you NSApplication object. But in reality it is a good best practice and any non trivial app will have that and a lot more.
There's a lot of magic that happens when the C function NSApplicationMain() is called at the launch of your app.
The old and in many ways out if date book Cocoa in a Nutshell covers this well.
Yeah you pretty much describe how it works and what it's doing.
It's relying on the fact that NSApplicationDelegate is an informal protocol and it doesn't declare that Controller conforms to it and is using the NIB to kick-start the app.
I have been making applications for Mac with Objective-C for about a year now but due to not really understanding how to use classes properly I have only ever used the 'AppDelegate' files. I want to start using classes as soon as possible because from what I understand it's very bad practice to clump it in to one class. Basically, how do I have two windows, each controlled by it's own class. I understand how to make objects similar to NSString or something but don't understand how to have classes that control windows etc.
Thanks
Edit: Basically I want to know how to split up my application in to classes.
If I understand you correctly then you need to create individual controller classes sporting their own IBOutlets and IBActions and hook these up to your UI elements. To split up an existing application into smaller classes requires some knowledge of Object Oriented programming.
Alternatively, you might benefit from reading this (or a similar) book:
'Cocoa Programming for Mac OS X' by Aaron Hillegass.
Try looking for NSWindowController in the docs. You create a custom subclass of NSWindowController and a xib file for it. In the xib file, make sure you set the class on the File's Owner to your custom subclass, and make sure its window outlet is connected to the window in the xib. If all that sounds totally foreign, head for the books! =)
Then, in the code where you want to bring this window onto the screen, you create an instance of your custom subclass and associate it with the xib, like so:
MyCustomWindowController *controller = [[MyCustomWindowController alloc] initWithWindowNibName:#"myxib"]
[controller showWindow:self];
The xib loading system will hook up all your custom outlets and actions on the new controller, and you can show it or do other wonderful NSWindowController things.
I've built an iOS 5 iPad app which makes use of a second screen. We have an admin view (on the iPad) and an external view through an HDMI enabled TV connected via the Apple DVI adapter. Both the iPad view and the TV view get the same data updates from a service call which is made every few seconds. We then present the data received as a series of charts; the charted data is presented very differently for the TV and iPad views - but the core dictionary of data is the same. I'm wondering about an elegant way to architect this solution. At the moment I have one of the view controllers (the admin iPad VC) doing the service calls using GCD and then dispatching NSNotifications which update the data (charts) properties on the other (TV) view controller. I'm considering moving the service calls away from the VC and creating a singleton which is initialized in the app controller. I then (somehow) set the two VCs as delegates and they get updated using a simple protocol. I'm not entirely sure if this is a good approach or if I should consider something else? Can I even set both VCs as the delegates of another class or is it typically only one delegate per class instance?
Thanks for any input.
Ben
Why not abstract the chart data into its own model class, which you can share in both view controllers? The model class can be responsible for fetching the new data. To make the controllers aware of updates, they can either use KVO on the model object, or they can observe notifications sent from the model object when an update occurs, or you can have an array of delegates for the model object and each view controller can be a delegate.
There doesn't seem to be any compelling reason to make it a singleton, although you can if you really want.
I'm coding my first app in XCode 4.2 supporting iOS 4.x through the current releases. To support iOS 4.0, I'm not using Storyboard feature and also using unsafe_unretained for weak references. I have AppDelegate files (.h and .m) along with several view controllers with UITabBarController. In my first view controller, in the -viewDidLoad method, I initialize two NSDictionaries and also start a timer with 1 sec interval. In the selector method, I have to pickup a random number between 0 and 7 to pick a corresponding value in both the dictionaries. The dictionaries are used only in the first view controller and not anywhere.
My first question is
where do I load those two dictionaries - in the AppDelegate -didFinishLaunchingWithOptions: method or in the first view controller's -viewDidLoad method?
I also wanted to support iPad. If that's the case, do I create a common class library to support iPhone/iPod/iPad?. If that is the recommended way, can I move the common functionality to the AppDelegate .m file instead?
Please advise.
You can move your common data and business logic into a separate set of model classes outside of the UI layers and appdelegates. This is one of the main benefits of the MVC pattern - by separating and making a clear distinction, it's easy to have separate view layers (one for phone and one for iPad).
That means all the data (dictionaries), logic with your random numbers and timers would be encapsulated and shared. That also allows you to cleanly unit test the majority model and logic programmatically. It also means you can make substantial changes to your algorithms and minimize the code churn.
When the timer goes off it can either post a notification or you can have a delegate pattern where it does a call back.
Related Post: Delegates vs. events in Cocoa Touch
If you do a shared model, one option is to use a singleton pattern where you access the model like:
[MyModel sharedInstance];
You should keep your code and data together if possible, which means that if you only access the dictionaries in your view controller then you should initialize them in the view controller's viewDidLoad.
I recommend keeping stuff out of the app delegate if possible or else you'll end up with a weird monster class that does too much stuff for which it shouldn't be responsible. If necessary, create one or more classes that manage common data (for example using the singleton pattern).
Whether you can/should use a common file for both iPhone and iPad depends on a number of factors. The main factor is: how different are the UIs? If they are very similar then use one class for both. You can also create a base class with common functionality and sub classes for iPhone and iPad which implement the necessary differences.
I'm writing a Cocoa application where I have an auto generated app delegate:(MyAppDelegate.h/MyAppDelegate.m)
So I am not sure of the best way to structure the class files for this Cocoa application. I understand MVC thoroughly (on the iPhone) but I'm having a block as to try organising the source properly in a Cocoa app.
I need to spawn two separate fullscreen OpenGL views. The problem is that I could simply create classes for "OpenGLView" then instantiate and call all this code into the app delegate, but it seems messy and it's aparently not the place to do it.
How would I best achieve the code structure?
Instantiate your application delegate in the MainMenu.xib file and hook it up. When I've done Cocoa fullscreen stuff, I've instantiated the views in the -applicationDidFinishLaunching method of the application delegate. It *is* messy, because for fullscreen views it doesn't really make sense to use interface builder. This is the same way that other folks do fullscreen apps in Cocoa.