iPhone SDK basics, one view available from several classes - iphone-sdk-3.0

I'm curious if it's possible to create an application according to window-based pattern, add UILabel, create a new class, and to be able to change UILabel's value from this new class.
After creating all that files we will have:
NewApplicationDelegate.h, .m;
Newclass.h, .m;
MainWindow.xib.
The IBOutlet in this case must be added to MainWindow.xib, and I want to change its value from NewCalss.m. Is it possible? How can I do that?
The point is that I was working only with navigation-based or simple window-based applications before, and now I need to have one view available and changeable (UILabels, for example) from at least 2 other classes.
Thanks.

You will have a UIController object too - right?
That has a handle on the UI elements, UILabel etc, whichever you map through.
You could pass this to the Newclass or you could provide an interface/protocol that the controller exposes that allows Newclass to interact with what you want to do.

Related

Using separate .nibs and getting logic out of App Delegate

I have a document based app using the standard template. I have two auxiliary panels in Main Menu.xib, and my main logic is currently in the App Delegate, mainly through an IBAction in App Delegate triggered by a button on one of my panels. Everything works fine, but I know it should be organised better.
I have implemented a Preferences panel as suggested by Hillegass in Chapter 12. So:
Create a custom controller called AppController containing instance
of PreferenceController. This is instantiated in Main Menu.xib
Custom PreferenceController class which is subclass of
NSWindowController. This loads the Preferences.xib
Preferences panel created in Preferences.xib
Before I get too far in the app’s development, I want to be sure I’m organising things the right way.
I want to move my main logic out of App Delegate, possibly into App Controller. I want App Controller to be in charge of showing and hiding the various panels, and I want each panel to have its own .xib.
I have created two more subclasses of NSWindowController and made them ivars of the AppController, alongside the PreferencesController eg. Panel1Controller & Panel2Controller.
My problem is that interface builder is not letting me connect an IBAction in AppController to a button on one of my panels. It only lets me connect to the .xib file’s owner, i.e. Panel1Controller in the case of Panel1.xib.
If I put the logic in Panel1Controller, how do I get at one of the other panels (say Panel2Controller?) in order to hide it?
Am I going about this the right way?
Getting very confused….
Any help much appreciated!
Regards,
John
Just for simplicity sake I'd move all the nib elements controlled by the NSWindowController sub-classes out of the main nib and into nibs with the same name as the (NSWindowController) sub-classes that control them. DON'T expose IBOutlets or IBActions in the sub-class headers (they should be in a class extension ("#interface MyWindowController ()") in the source file for that sub-class.
Also, is the AppController a 2nd app delegate? Probably not what you want (there can only be one); you should merge its logic into the existing app delegate if that's the case.
I just came across this method.
This seems to do away with NSWindowController altogether, and make the AppController the file's owner of both .xibs. This way IB allows you to create outlets in AppController for each window, and contain actions.
I have created a very simple, two-window app using this method that hides one window when a button on the other is pressed. Before I go away and re-organise my main app, I want to be sure I'm doing this the correct, standard way, if there is one?
This page contradicts this method, by saying one window = one .xib + one NSWindowController subclass.
If you do it the latter way, how can one window talk to another, when you can't create outlets/actions in the AppController? Actions implemented in a window's NSWindowController class can't see outlets of another window, so how can they communicate?
This seems like pretty standard, basic stuff and yet I cannot find any sources which say which way is correct/best practice.
Another method I have read about here mentions using Notifications.
I'm still wondering though - which is the most common "accepted" method of loading two or more windows in separate .nibs and getting them to talk to each other? I'm surprise this info has been so hard to find.
If you're going to follow this pattern, separate AppDelegate and AppController, then your MainMenu.xib should not contain any window objects of any kind...it should just contain the application menu. Each additional window (NSWindow/NSPanel, etc.) gets its own .xib and its own NSWindowController.
There are two ways to assign references to your properties (IBOutlets) and methods (IBActions): 1) programatically, 2) via Interface Builder. Let's cover the second method!
To be able to wire things up from Interface Builder (IB) you will need a reference to the target object inside IB. For the MainMenu.xib file, this gets setup automatically: the MainMenu.xib contains an "AppDelegate" Object reference. The Object reference exposes the properties and methods in the AppDelegate class that are prefixed by the "IBAction" and "IBOutlet" macros. I write Object (with a capital O) because it is a widget available in the "Object Library" in IB.
You can easily create an instance of a custom objects inside a .xib file (via IB) by dragging an "Object" widget from the Object Library into your .xib. Then set the Object's class to that of your custom class. Once you've done this, the IBActions and IBOutlets in your custom class object will be available in IB. [Note: one thing to remember when doing this, is that when you load the xib, the object will be instantiated automatically. No need to alloc and init from within AppDelegate...you still have to call showWindow: on it].
As you mentioned, another approach is to simply have all of your additional .xib files owned by the AppController. That would be convenient, but it also gets 100% away from the architecture that you were trying to follow in the first place. In other words, if you're going to follow that style, why not just skip the separate AppDelegate and AppController in the first place, and just stick with the former (which would then be a Controller and Delegate).

Cocoa - explanation of view handling

I'm learning Cocoa at the moment, and have followed 'generic' tutorials on getting a basic form with a button and label.
With the .xib, I've added an 'Object' (instance of NSObject subclass), and have also created a ViewController class, which I connect to my view by setting Custom Class to ViewController. I then code up my ViewController.h and .m files adding a pressedButton method, and a label (myLabel). This all works OK (ie. the label updates when the button is pressed).
My question is: what am I actually doing with this process in C++ terms (a language I'm more familiar with)? As I understood it, my 'Object' (set to class ViewController) represents an instance of the .xib file (may be wrong here), and with this set to the ViewController class, I'm able to make outlets and actions in ViewController.h/.m, but I'm still not sure what's really going on behind the scenes.
Lastly, the XCode template provides an AppDelegate class 'free'. Given I'm managing my controls via my ViewController class, what would this file/object be used for - is it for application specific things that do not relate to the view itself, or is it also used to manage the controls on the form too (like you see in some tutorials I think)?
I hope, I understood the first part of your question well. The .xib (xml verison of nib file) does not represent a class or object. It is rather used to create a view object with all its subviews (each an object) and link it properly to your view controller.
It is most common and automatically generated that way, that the underlying view within your nib file corersponds to self.view (from your view controller's point of view).
You could access each view created by the nib file by navigating though the subview hierarchy of self.view. Alternatively you could define tags within nib/IB (Interface builder) to access individual view objects more easily.
"Just for your convenience" the IBOutlets were introduced. You can define an IBOutlet in the interface of your view controller and link it using IB to the dedicated object that is created using the xib file.
I am saying "Just for your covenience" because it is not really neccessary, considering other ways of addressing your view objects. But it is more than convenient and therfore strongly recommended and stimply the standard way of doing it.
You could even add further views programmatically to a form/view that was created using IB. You can change properties of those views programmatically.
The view and the subvies are created in that very moment when your view controller is initialized with a nib file using the initWithNibName:bundle: method. Then the nib file (xib these days) is opened, its content is parsed and interpreted and all views are created and added to their superviews respectively and their properties and action: selectors etc. are set accordingly. Again, the whole process is designed for your convenience. You could even create all the views etc. programmatically - witout any nib file at all. The loadView method of your custom view controller would be the appropriate place of dong so.
Second question:
AppDelegate is designed for application wide actions etc. If you can manage everything fine within your view controllers then you would not need to change anything on the AppDelegate.
It is often used as a container for variables or functions of global character (which are then properties and members of the app delegate object). Sometimes you may see it neccessary to override some of the AppDelegates methods like application:didFinishLanuncing or applicationDidBecomeActive.
Strictly spoken, UIApplicationDelegate is no class that you subclass. It is a protocol that you implement. (Very much like interfaces within Java - sort of overcoming the lack of multiple inheritance that you are familiar with from C++).

How to use classes to control windows in Objective-C

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.

"Global" UIImagePicker Functionality for Multiple Classes

I'm working on an app that (among other things) uses UIImagePicker to grab an image from the device once the user has selected the SourceType by tapping the appropriate button. Different sections of the app will need to use this functionality, as well as the variable holding the image information once selected. When I first started the project I had all of my code to do this in a single class named ViewController. I'm now working on moving the individual sections of the app into their own classes, but I'd like to be able to have them all use the UIImagePicker functionality from a central location.
Along with the necessary UIImagePickerController methods and protocols, I have a method that presents a view with buttons for each available SourceType. Each of these buttons then send a message to methods to show the appropriate picker (or the camera). Once an image is selected, it is applied to a variable for use by the different sections.
I wanted to get suggestions on the best way to approach this before I went to deep down the wrong rabbit hole.
Thanks!
If a lot of your classes use this functionality, you can create a superclass (itself being a subclass of UIViewController).
This class will expose some method to launch the process you described, and some other to gather the information collected.
If you don't want to use inheritance, or you already to with another class, you can also create a separate class responsible for this process.
This class, which is not necessary a UIViewController, has to be instantiated and then called the same way the superclass described above.

Why can't new ObjC classes descend from UIViewController?

So, I've been making iOS apps since the first iPod touch came out, but something has always flabbergasted me; why is the list of new Cocoa Touch classes restricted to subclasses of NSObject, UIView, and UITableView? I routinely make subclasses of UIImageView and UIViewController.
Am I "Doing It Wrong™?" Have I totally misunderstood MVC to the point where I make Controller classes where I shouldn't? What is the philosophical reasoning for requiring classes to never descend from a basic controller class?
What gives you the idea that you aren't supposed to subclass UIViewController? This is directly from the documentation for UIViewController:
In a typical iPhone application, there is usually at least one custom subclass of UIViewController and more often there are several.
The C of MVC is supposed to be the least re-usable part it's whole job is to mediate between M & V. If you find something that is in the C section of your code that you have to copy and paste into several subclasses of a given object or into several projects that code should be moved elsewhere.
If you are just basing this off the fact that there is not a nice popup menu item that says UIViewController, don't worry about it Apple has just not bothered to write a template file for that class yet.
Uhm... maybe it's just me, but I see a UIViewController subclass template when I choose new File.
UIViewController template http://files.me.com/aclark78/obnp83
Like #theMikeSwan says, there simply aren't GUI templates for this when you create a new class in Xcode GUI. But you can always create a new subclass whose parent is initially NSObject. After that, you just go to your code and change the parent class to whatever you like.
So... no, you are not doing it wrong in the sense that you rightly understand that often you want to subclass UIViewController; but yes, you are doing it wrong since you assume you shouldn't do this only because Xcode GUI does not support it :)