setup coredata, before appdelegate loads my mainWindow.xib - iphone

I have setup coredata in my appDelegate, but it first loads the mainWindow.xib and the corresponding controllers+views in that xib file. Those controllers need to have a managedObjectContext to load properly. And after the xib is unarchived it runs the code in my appDelegate.
How can i setup my coredata and then load the mainWIndow.xib? Or just make sure coredata is initialized properly before unarchiving my mainWindows.xib?

You could override awakeFromNib on your UIApplicationDelegate subclass, and setup Core Data there. This method will be called once all objects has been unarchived from your nib file, but before their instances begin to do their work. See awakeFromNib as your last chance to tweak any behavior before the instances start running.
Observe:
When overriding awakeFromNib you must call [super awakeFromNib], or else your superclass might not initialize properly.
The order of the calls to awakeFromNib is undefined, so you may never send messages to any other objects from the same Nib from within awakeFromNib. As a bonus this also means that awakeFromNib is guaranteed to run before any other object in the same Nib needs your services and sends any messages to you.

Related

How to make a delegate object accessible throughout a ViewController

I'm trying to get an instance of my AppDelegate accessible to all methods in each ViewController that I have. If I try to declare it with other class variables I get Initializer Element is not a compile-time constant. If I declare it in a method within the ViewController however I am able to use it. I am trying to save integers and floats to properties I have set up in the AppDelegate (a big no-no I know, but this is a project for an introductory class and I'm not expected to get too advanced, especially since everything we've done so far is not compliant with the MVC paradigm). The app uses a toolbar to switch between views using the app's ViewController to load the other ViewControllers as subviews. I was going to put the AppDelegate declaration and update statements in the ViewDidUnload method of each view controller, but I'm not sure that the Views are unloaded whenever they are switched (they're switched by removing the current View from the SuperView and loading the new one as a Subview at index 0). What happens to the views that are not currently being viewed then? Is there a method that detects that that I could implement the AppDelegate declaration and updates into?
I guess ideally I'd like to be able to access the AppDelegate object in any method in my ViewControllers because I have a lot of quantities being updated throughout and would like to have those quantities updated in the AppDelegates values as soon as they happen, since I'm not sure what happens with a View is cleared from SuperView
Thanks in advance everyone
You can access your app delegate via [[UIApplication sharedApplication] delegate] from anywhere in your application.
You should never instantiate another copy of the object on your own. The system does this for you at startup.
As for detecting changes, you can override the viewDidDisappear method of UIViewController. (You're correct--in general, they will not be unloaded when switched, and viewDidUnload will not be called)

UITableViewController loading inside a UIViewController inside a UIViewController issue

I don't really know if what I'm doing is the right way to do it. Right now it seems to be working until it hits a certain point with a EXC_BAD_ACCESS message.
I'll describe what I'm doing as best and with the most relevant details I can tell:
I have a CalendarViewController that inherits UIViewController which is loading from a .xib file (CalendarViewController.xib). The class contains a UIView called contentView which I created and which I initialize with another nib file based on a class which is also inherited from UIViewController:
- (void)viewDidLoad {
[super viewDidLoad];
calendarView = [[CalendarView alloc] initWithNibName:#"CalendarView" bundle:nil];
[contentView addSubview:calendarView.view];
}
(calendarView is the class inheriting UIViewController and viewDidLoad is from CalendarViewController.
CalendarView.xib has a UITableViewController with it's respective UITableView. This Table View Controller is linked to a CalendarTableController to which I also generated a .xib file for it.
Everything is being created just right (apparently) but it is crashing somewhere very unexpected. CalendarTableController also implements a DateLoaderDelegate which loads information from an xml on an external url.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// When the data has all finished loading, we set a copy of the
// loaded data for us to access. This will allow us to not worry about
// whether a load is already in progress when accessing the data.
self.lastLoadedMatchXMLData = [self.matchXMLData copy];
// Make sure the _delegate object actually has the xmlDidFinishLoading
// method, and if it does, call it to notify the delegate that the
// data has finished loading.
if ([_delegate respondsToSelector:#selector(xmlDidFinishLoading)])
{
[_delegate xmlDidFinishLoading];
}
}
The application is getting to this point without any problem. _delegate is containing the correct object (a CalendarTableController which implements the DateLoaderDelegate). But when it arrives to the line:
if ([_delegate respondsToSelector:#selector(xmlDidFinishLoading)])
it crashes with the EXC_BAD_ACCESS, I don't really know the reason, if I look at the debugger, the crash is not occurring in any of my classes as any of them are appearing in the execution stack. URLConnectionClient seems to be generating it, but I don't really know why. The loading of the xml had worked earlier before I rearranged the ViewControllers to work as I have described now.
Any ideas?
It's weird. I fixed the problem but I had to dedicate the whole UIViewController to contain the UITableView. What I did was this:
Create an IBOutlet with the custom UITableViewController (CalendarTableViewController) in the custom UIViewController.
In the loaded .xib file I linked the IBOutlet to a created UITableViewController declared as a CalendarTableViewController.
This way I solved the problem of the UITableViewController being deallocated without reason. But now the image views I had placed in the intermediate UIViewController wouldn't appear. I had to set that UIViewController to contain solely the CalendarTableView and place the image views in the initial UIViewController. Weird, isn't it? I don't like much the hierarchy I created... but for now that will do =S
Check that you have defined properties for all of your subviews and that you are retaining everything that you need to be. Bad Access May mean that you're attempting to call respondsToSelector on an object that has been released.
Have you tried calling loadView before adding the nested controller's view to the parent's view?
Maybe viewDidLoad is not executing before you add the view and some variables were never initialized.

How to pass references to init method of object in a nib?

I have a UIView subclass which currently assembles itself completely programatically. It has a custom initWithFrame:bundle: initializer which is necessary because it uses the bundle passed in to load image resources.
I want to make this view a subview in a larger nib file, but then initWithCoder will be called when the nib loading code gets to it instead of my custom initializer. Is there any way I can place this view in a nib and still have my custom initialization occur?
Yes, you can override initWithCoder: too if your bundle is known ahead of time (read: You don't need it passed in as a parameter). Otherwise, nope.
If you can wait until awakeFromNib, you can do your initialization in there. You still have the problem of not being able to pass the bundle into the method, though. Since awakeFromNib is called after initialization and setup of all outlets and actions, it might be too late for you. Maybe it's better to redesign around the nib-loading system anyway?

Automatically Loading XIB for UITableViewController

Ran into something interesting, want to know if I'm doing something wrong or if this is the correct behavior.
I have a custom UITableViewController. I ASSUMED (first mistake) that if you initialize as such:
[[CustomTableController alloc] init];
it would automatically load from a XIB of the same name, CustomTableController.xib, if it is in the same directory and such.
HOWEVER
This does not work; doesn't load the XIB. BUT, if I change the parent class of my controller from 'UITableViewController' to 'UIViewController', EVERYHTING WORKS FINE!
Calling:
[[CustomTableController alloc] init];
loads the controller and view from my xib.
Am I doing something wrong? Is this a bug? Expected behavior?
Most of the classes in Cocoa Touch list a "designated initializer" that you're supposed to call from your init methods when you subclass them. When you create your own custom class, it's a good idea to check the documentation to find the designated initializer for your superclass. When you initialize the class using some other initializer from a more general superclass (which you're doing by calling - [NSObject init] in this case), you rob your direct superclass of its opportunity to properly initialize its state. Sometimes you can get away with this. Often you can't.
UIViewController's documentation states that its designated initializer is -initWithNibName:bundle:. If you call this method with a nil nibName, it will look for a nib that matches your class name. The behavior of -init is undocumented for UIViewController. Based on the behavior you're seeing, it seems like it may be calling [self initWithNibName:nil bundle:nil], but it would be safer to call initWithNibName:bundle: directly rather than relying on this undocumented behavior.
UITableViewController only defines a single initializer, -initWithStyle: (although it doesn't specify this method as the designated initializer). This method initializes your UITableViewController without using a nib, which is usually fine. Since you don't add subviews to a UITableView, there usually isn't much to be gained by configuring your UITableViewController via a nib.
If decide you want to configure your UITableViewController via a nib anyway, the documentation tells us that we can safely bypass -initWithStyle: and call UIViewController's initWithNibName:bundle: method. Here is what the documentation tells us about how our UITableView and its controller will be initialized in each case:
If a nib file is specified via the initWithNibName:bundle: method (which is declared by the superclass UIViewController), UITableViewController loads the table view archived in the nib file. Otherwise, it creates an unconfigured UITableView object with the correct dimensions and autoresize mask. You can access this view through the tableView property.
If a nib file containing the table view is loaded, the data source and delegate become those objects defined in the nib file (if any). If no nib file is specified or if the nib file defines no data source or delegate, UITableViewController sets the data source and the delegate of the table view to self.
In summary, the documentation for most Cocoa Touch classes either specify a single designated initializer or a handful of initializers that you can call safely from your subclasses. Always refer to the documentation for your superclass to figure out which initializer your subclass should call.

whats the different between nibNameOrNil and ViewDidLoad methods?

whats os the difference between initWithNibName and ViewDidLoad methods ?
can i use them both?
initWithNibName - is what you call to create a view controller from specified nib file.
viewDidLoad - is what system calls on your controller after the controller’s view is loaded into memory. You can implement this method to perform some additional initialization (which is not done in nib file)
I think you may be confusing things here. nibNameOrNil is (usually) an argument name, frequently for -initWithNibName:bundle:. As such, it should be the name of your nib (.xib) file. -viewDidLoad is a method, and is called after your viewController has had it's view instantiated for the first time.