I'm creating an iOS application with lots of custom views, so, using default Cocoa views was not an option. Then, I decided to go with the Coordinating / Mediator Controller design patter (learned in Apress - Pro Objective-C Design Patterns for iOS).
From the delegate, I create a rootViewController pointing to the view in my coordinating controller:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
coordinatingController = [C6CoordinatingController sharedInstance];
self.window.rootViewController = coordinatingController.activeVC;
[self.window makeKeyAndVisible];
return YES;
Then, in the coordinating controller, I have singleton creation methods:
+ (C6CoordinatingController *) sharedInstance{
if (sharedCoordinator == nil){
C6Log(@"New Shared Coordinator");
sharedCoordinator = [[super allocWithZone:NULL] init];
[sharedCoordinator initialize];
}
else {
C6Log(@"Return Singleton Shared Coordinator");
}
return sharedCoordinator;
}
+ (id) allocWithZone:(NSZone *)zone{
return [self sharedInstance];
}
- (void) initialize{
C6Log(@"");
[self checkDevice];
_mainVC = [C6MainViewController initWithDevice:device];
_activeVC = _mainVC;
[self checkLanguage];
[self chooseFirstView];
}
I also have a selector to choose the first view (I only have two at this time):
-(void) chooseFirstView{
// If a language was not setted, go to language settings view
if (!language) {
C6Log(@"Going to Language Settings");
C6LanguageSettingsViewController *languageVC = [C6LanguageSettingsViewController initWithDevice:device];
[_mainVC.view addSubview:languageVC.view];
}
else {
C6Log(@"Going to User Settings", language);
C6AccountSettingsViewController *accountVC = [C6AccountSettingsViewController initWithDevice:device];
[_mainVC.view addSubview:accountVC.view];
}
}
Then, I have an IBAction to be used by my views:
- (IBAction) requestViewChangeByObject:(id)object {
int buttonTag = [object tag]; // dividend
int viewTag = buttonTag / divisor; // quotient
int actionTag = buttonTag - (divisor * viewTag); // remainder
C6Log(@"viewTag: %d | actionTag %d", viewTag, actionTag);
switch (viewTag) {
case LanguageTags:
C6Log(@"LanguageTags");
break;
case AccountTags:
C6Log(@"AccountTags");
break;
default:
break;
}
In the NIB, I created an Obect (Coordinating Controller) an I call the IBAction from there. It works just fine and I can change my views (it still needs to be implemented)………
BUT… I also want to change the language, but, as it is not a navigation issue, I wanto to do it from the C6LanguageSettingsViewController and not from the C6CoodinatingController.
So, I created another IBAction in the C6LanguageSettingsViewController:
- (IBAction)chooseLang:(id)sender{
UIImage *bt;
[self resetImagesToNormalState];
C6Log(@"");
C6Log(@"%@", [sender tag]);
C6Log(@"%@", sender);
.
.
.
When I connect the button to this IBAction (through File's Owner OR via an LanguageSettingsViewController object), the app breakes and, sometime it shows no error and, sometimes it presents Unrecognized selector sent to instance OR EXC_BAD_ACCESS (Code=1, address = 0x………) in the UIApplicationMain.
I believe the problem is the NIB doesn't find the file's owner… but I'm not sure how to solve it.
Ok… it seems absurd, but I'm answering myself :P
I managed to make it work (finaly!) and I found I was managing the viewControllers in a BAAAAD way, so, I changed some code in the coordinating controller:
First, I don't have a "real" mainViewController with NIBs and stuf no more…
OLD initialize
NEW initialize
checkDevice verifies if it's iPhone or iPad, so I can choose the right NIB.
checkLanguage checks the [NSUserDefaults standardUserDefaults] for the language
Finaly, I call chooseFirstView:
OLD chooseFirstView
NEW chooseFirstView
The big change is WHEN and HOW I initiated the _activeVC… AND the fact that both _languageVC and _accountVC are now global variables.
Well, after this changes, the NIB button call both IBAction methods: it's file's owner and the coordinating controller.
Another BIG thing about using this kind of pattern is how to change from one view to another without explode iOS device memory… here's how I do it inside the coordinating controller:
In the beginning of the method, I do a lot of math… I "created" a pattern where each NIB should have it's tags beginning with 100 multiples… so, language begins with 0, account with 100………
Then, the way I change from one view to another is right there:
I really hope this helps who's trying to use this coordinating controller pattern :P