What's the purpose of the AppDelegate and ViewController files that Xcode generates? - iphone

I have written a few functioning iPhone applications, but mostly by following tutorials that tell you where to write the code. As a result I have gone without understanding what these files are actually designed to hold.
I made an app with code that is in the application method of the AppDeleagte file, so it gets called when the program runs. I wanted to make this code run on a button press instead, so I added a button, but when I came to put the code in the relevant IBAction, I realised all the variables and methods i needed were in the AppDelegate file, so I couldn't use them in the ViewController file.
So my immediate question is "how should I organise my code so that I can have it run on a button press?", but an explanation of the concepts behind it would be great too, becuase then I can do it without asking next time.

In short, the AppDelegate deals with application level events. Example: application becomes inactive, application starts etc. So whatever you need to setup when the application starts can go in there. As for your problem, I would suggest moving the variables to perhaps a singleton class or have another class that just contains variables and methods as a member in your appdelegate and do like madhu suggests. Having variables and methods directly in your app delegate works, but it can become big and nasty after a while.

import "AppDelegate"
in implementation file of viewcontroller
AppDelegate *app=(AppDelegate*)[[UIApplication sharedApplication]delegate];
[app inappDelegateDeclaredFunctionname];

Related

Understanding application flow of iOS 7 apps. What happens on launch?

I'm new to Objective-C and iOS programming. I've read through a few of Apple's "Getting Started" docs and I've downloaded a few sample applications to try and get familiar with what is going on in the app. What I'm confused about is what exactly happens from the application's launch. I see in main.m that UIApplicationMain gets called and invokes the AppDelegate. From what I've read, now, if applicationDidFinishLaunching returns true, the app will enter the main event loop.
Is this all correct? If so, how do I tie my code to events? Where do I create instances of my classes when an event occurs?
Finally, from my understanding, Xcode now creates all template apps with storyboards. However, some applications I am looking at are a bit older and don't use storyboards, but I don't see .xib or .nib files anywhere in the directory, but the applications successfully build. Am I wrong in assuming that applications require these files?
An application does not require a .xib or .nib to run. Many programmers do not use any of the visual design tools that generate storyboards or .nib files. You can define your UI completely in code if you wish.
The call to UIApplicationMain in main.m creates a singleton UIApplication object, sets up an event loop, and sets up your UIApplicationDelegate which works in tandem with UIApplication so you can customize the behavior of your app at key points in its lifecycle. UIApplication manages the event loop for you. It receives events from the system and dispatches them to your code for handling.
In order to really understand event handling you need to understand the responder chain. If you look at the superclass of your app delegate you will see it is UIResponder. This is the interface that lets objects respond to and handle events. It is the superclass of UIApplication and UIView and handles most of the raw event handling for you. Events follow a defined path through your code. In the simplest case, touch events, UIApplication pops an event from the event loop and hands it off to UIWindow. UIWindow will perform a hit test to try and deliver it directly to the UIView under the finger. It gets more complicated and motion events take a different path but the point is that much of the raw event processing is handled for you by UIKit. All you really need to do is setup your UIWindow and its rootViewController and events will follow a specific delivery path through all your UIKit responders. You can read about the responder chain in detail here https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html.
When your app starts, the following delegate methods will get called in this order:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
- (void)applicationDidBecomeActive:(UIApplication *)application;
In addition, your initial view controller will get created and shown and the following methods will get called (assuming you are using storyboards or xib files):
-(void)viewDidLoad;
-(void) viewWillAppear:(BOOL)animated;
As for "tying your code to events", what type of events are you talking about? What are you trying to accomplish?
You no longer need to use xib files if you are using storyboards, however, you can if you want to.

Is setting a pointer from a singleton to a viewController and updating GUI a violation of MVC

I'd like to ask a theoretical question pertaining to good code practice and the MVC model, Here is the case:
The design contains a RootViewController and a singleton class. The singleton acts as a controller with a timer objects that should be available throughout the app. The timer object consists of a UISwitch and an NSTimer, they are both owned by the singleton controller so the UISwitch can be added to new viewControllers on demand and the timer object is accessible throughout the app.
In order to update the RootViewController's screen with the current timer's count i created a pointer in the singleton to the RootViewController and have the RootViewController set itself to that pointer, similar to [singeltonOBject setDelegate:self].
Using this design the UILabel of the RootViewController can be accessed and updated from the singleton when the timer ticks. I chose to do that because i didn't have time to implement a regular delegate.
Note that the RootViewController is owned by the AppDelegate and the the singleton class is obviously NOT owned by the RootViewController. Therefore there is no retain cycle.
Question:
Is the setting of a pointer from the singleton to the RootViewController and updating the UILable from the singleton controller a violation of good coding practice, are there any basic principles that are not fulfilled?
Thanks for your answer!
Problem
Generally when something doesn't feel quite right, thats because it's not.
While your code will work it is not going to be easy to maintain in the future and is liable to breaking. Even if you never plan on looking at this code again, it is always good to practice good coding conventions.
I recommend reading The Pragmatic Programmer which contains lots of tips for programmers on how to write better code. One of those tips is Minimize Coupling Between Modules. Right now your RootViewController knows about your Singleton and your Singleton knows about your RootViewController so they are both coupled to each other. In the future, when you change one you are likely to have to change the other one as well.
What if you want to add another label?
You will have to add the label in the RootViewController and then change your singleton to update that label as well.
What if you remove the label altogether? Lets say you go back to this in a years time and remove the label, suddenly there is another class that is not compiling and you might not remember why. You have broken code in a completely separate part of your application.
As for following MVC, this is in violation of that. Your view is being modified by something separate. If MVC is setup correctly you should be able to put on as many views as you want without having to change any code that is controlling data, in this case your timer.
Now as for memory management, your RootViewController is now being retained by this Singleton. Singleton's exist for the entire life of an application. You are right that you do not technically have a retain cycle however your RootViewController will now never be deallocated. In most applications this does not matter as the RootViewController always remains at the bottom of the stack but it is a coincidence and thus cannot be reliably programmed on. This is actually another tip from The Pragmatic Programmer, Don’t Program by Coincidence.
Solution
A better solution would be to use a notifications if you really need a global timer like you say (another story is that your global timer singleton does not sound like a good idea). Whenever you were updating your label from within your singleton you can fire a notification instead. Your RootViewController will receive this notification and can update its label. You can pass data in a notification if needs be. Now in the future if you make a change to the view and want to update something else you only need to change code in one location (The RootViewController).

Should I be writing the majority of my code in a controller or the delegate?

I was using Xcode 4.1 and after upgrading to 4.2, things started to become out of date. I am using many examples from different books, such as Big Nerd Ranch Guides, which do not use Storyboards and the Windows-Based Application had been changed to "Empty" Application.
With these new changes, I feel like the books and tutorials I had been using to start have become outdated. In many of these examples, they say to write the methods and variables in the delegate header files for 4.1. With the new 4.2 Xcode, there is an AppDelegate and ViewController. Should I still be writing the methods and class members in the AppDelegate, or should I be now writing them in the Controller file?
I am confused. Does Apple now want us to create our controller and reference it through the delegate?
When your app is run, it creates an instance of UIApplication. You want to know things that only the UIApplication object knows (did we just get switched to the background? did we just open?) so you use the delegate pattern to get it. When you start a new project Apple starts you off with an already-assigned App Delegate. You can open up MainWindow.nib and inspect your App Delegate to see how it is connected to your UIApplication instance (File's Owner, in this case).
In general you only want to put code in there that has to do with the basic functionality of your app. Launch, quit, go to background and come to foreground are when you'll be doing things in the App Delegate.
Most everything else should go in your view controllers or model objects. Since 'delegate' is just a design pattern, your view controllers can be delegates of other objects. For example, if you present a UITableView, you will assign a view controller as it's delegate in order to respond to events such as selection and scrolling. Your app has many delegates, but it only has one App Delegate.
The AppDelegate is really just a "launcher" for your app. Ie: You shouldn't be writing much code in it at all.
If you're concerned with "set up" code, do it in your View Controller, under viewDidLoad.

Difference between AppDelegate.m and View Controller.m

Could anyone tell me when we use the AppDelegate.m and AppDelegate.h during iPhone programming? I have used only the ViewController.m and ViewController.h for basic learning. I just want to know when and why AppDelegate is used.
Both define classes, but the classes are used for different things. ViewController.h/m define a view controller class that manages a hierarchy of views -- basically, one screen of an application. You might have multiple screens that each have their own view controller.
AppDelegate.h/m define a class that manages the application overall. The app will create one instance of that class and send that object messages that let the delegate influence the app's behavior at well-defined times. For example, -application:didFinishLaunchingWithOptions: is sent when the app has finished launching and is ready to do something interesting. Take a look at the UIApplicationDelegate reference page for a list of messages that the app delegate can implement to modify the behavior of the application.
I would like to add the following to #Caleb's answer.
If care is not taken, the AppDelegate could easily become one of the most accessed objects in the application. I usually refrain from calling methods in the AppDelegate from any of my ViewControllers. Unless, something needs to be reported to the AppDelegate that would influence the behaviour of the whole application.
I keep my AppDelegate for the following:
initialization: whatever needs to be done on the very first launch (after an install or an update)
data migration from version to version (e.g. if you use CoreData and migrations)
configuration of objects linked via IBOutlets from MainWindow.xib
determining the initial orientation to launch in
saving uncommitted data / state prior to the application being terminated or entering background mode
registering for the Apple Push Notification Service and sending the device token to our server
opening one of the supported application URLs (e.g. maps://)
For other use case scenarios and a more thourough description of the AppDelegate, see the iOS Application Programming Guide.
The view-controller. h/m is responsible of controlling the connection between your model and your view (more on MVC here).
AppDelegate. h/m is responsible for the life-cycle of your application. What to do when the user press the home button and exit your app, what to do when the app enter background. Things like this.

Can Objects Call the Main Application?

Please bear with me, this is probably a very simple problem for an expert but I'm new to the language.
I'm trying to create an application that dynamically generates and releases a series of views, which are displayed in the main window. The problem I am having is in swapping between them. I want each view to contain buttons that cause the view to change. I can make a view close itself, but I don't know how to order the main program to change its own view to something new once that's been done (i.e. message the main application from within one of its child objects). I suppose I could make the main view of the application into a global, but I'd rather be able to contact the main application directly as this strikes me as being somewhat neater and less prone to other problems. Problem is, I don't know the main app's identifier. The convenient 'self' identifier gets used so often that I've never seen a code snippet that contains an identifier for the main application that could be called from outside it. It would also be useful to be able to link NIB file objects directly to attributes held in common by the main program.
Am I going about this in entirely the wrong way? Is there a generic 'main app' identifier? Is it possible to create one, if one isn't generated automatically?
-Ash
Assuming that by 'main application' you mean your app delegate, you can get it using this method :
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];