我正在创建一个包含大量自定义视图的iOS应用程序,因此,使用默认的Cocoa视图不是一种选择。然后,我决定采用协调/中介控制器设计模式(在Apress中学习 - 适用于iOS的Pro Objective-C设计模式)。
从委托中,我创建了一个指向我的协调控制器中的视图的rootViewController:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
coordinatingController = [C6CoordinatingController sharedInstance];
self.window.rootViewController = coordinatingController.activeVC;
[self.window makeKeyAndVisible];
return YES;
然后,在协调控制器中,我有单例创建方法:
+ (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];
}
我还有一个选择器来选择第一个视图(我此时只有两个):
-(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];
}
}
然后,我有一个IBAction供我的观点使用:
- (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;
}
在NIB中,我创建了一个Obect(协调控制器),我从那里调用了IBAction。它工作正常,我可以改变我的观点(它仍然需要实施).........
但是......我也想改变语言,但是,因为它不是导航问题,我想从C6LanguageSettingsViewController而不是C6CoodinatingController中进行。
所以,我在C6LanguageSettingsViewController中创建了另一个IBAction:
- (IBAction)chooseLang:(id)sender{
UIImage *bt;
[self resetImagesToNormalState];
C6Log(@"");
C6Log(@"%@", [sender tag]);
C6Log(@"%@", sender);
.
.
.
当我将按钮连接到此IBAction时(通过文件所有者或通过LanguageSettingsViewController对象),应用程序中断,并且有时它没有显示错误,有时它会显示无法识别的选择器发送到实例或UIApplicationMain中的 EXC_BAD_ACCESS(Code = 1,address = 0x .........)。
我认为问题是NIB找不到文件的所有者......但我不确定如何解决它。
答案 0 :(得分:1)
好的......这看起来很荒谬,但我在回答自己:P
我设法让它工作(最终!)我发现我以BAAAAD方式管理viewControllers,所以,我在协调控制器中更改了一些代码:
首先,我没有一个带有NIB的“真正的”mainViewController,而且没有stuf ......
OLD初始化
- (void) initialize{
C6Log(@"");
[self checkDevice];
_mainVC = [C6MainViewController initWithDevice:device];
_activeVC = _mainVC;
[self checkLanguage];
[self chooseFirstView];
}
新初始化
- (void) initialize{
C6Log(@"");
[self checkDevice];
[self checkLanguage];
[self chooseFirstView];
}
checkDevice 验证它是iPhone还是iPad,所以我可以选择正确的NIB。
checkLanguage 检查[NSUserDefaults standardUserDefaults]中的语言
最后,我打电话给chooseFirstView:
OLD chooseFirstView
-(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];
}
}
NEW chooseFirstView
-(void) chooseFirstView{
// If a language was not setted, go to language settings view
_activeVC = [[UIViewController alloc] init];
UIImage *bgImage = [UIImage imageNamed:@"bg.png"];
UIImageView *bgView = [[UIImageView alloc] initWithImage:bgImage];
[_activeVC.view addSubview:bgView];
if (!language) {
C6Log(@"Going to Language Settings");
languageVC = [C6LanguageSettingsViewController initWithDevice:device];
[_activeVC.view addSubview:languageVC.view];
}
else {
C6Log(@"Going to User Settings", language);
accountVC = [C6AccountSettingsViewController initWithDevice:device];
[_activeVC.view addSubview:accountVC.view];
}
}
最大的变化是WHEN和我如何启动_activeVC ......以及_languageVC和_accountVC现在都是全局变量。
好了,在这个更改之后,NIB按钮调用两个IBAction方法:它是文件的所有者和协调控制器。
使用这种模式的另一个重要的事情是如何在不破坏iOS设备内存的情况下从一个视图切换到另一个视图...这是我在协调控制器中的方式:
- (IBAction) requestViewChangeByObject:(id)object {
int buttonTag = [object tag]; // dividend
int viewTag = buttonTag / divisor; // quotient
int actionTag = buttonTag - (divisor * viewTag); // remainder
C6Log(@"ViewTag: %d", viewTag);
switch (viewTag) {
case LanguageTags:{
C6Log(@"LanguageTags - button %d", actionTag);
accountVC = [C6AccountSettingsViewController initWithDevice:device];
UIView *fromView = languageVC.view;
UIView *toView = accountVC.view;
[self switchFrom:fromView To:toView usingAnimation:AnimationPushFromRigh];
}
break;
case AccountTags:{
C6Log(@"AccountTags - button %d", actionTag);
switch (actionTag) {
case 0:{
C6Log(@"Go back");
languageVC = [C6LanguageSettingsViewController initWithDevice:device];
UIView *fromView = accountVC.view;
UIView *toView = languageVC.view;
[self switchFrom:fromView To:toView usingAnimation:AnimationPushFromLeft];
}
break;
default:
break;
}
}
break;
default:
break;
}
}
在方法的开头,我做了很多数学...我“创建”了一个模式,其中每个NIB应该有100个倍数的标签...所以,语言从0开始,帐户以100 .........
#define divisor 100
#define LanguageTags 0
#define AccountTags 1
然后,我从一个视图转换到另一个视图的方式就在那里:
-(void) switchFrom:(UIView*) fromView To:(UIView*) toView usingAnimation:(int) animation{
C6Log(@"");
/*************** SET ALL DEFAULT TRANSITION SETTINGS ***************/
// Get the current view frame, width and height
CGRect pageFrame = fromView.frame;
CGFloat pageWidth = pageFrame.size.width;
// Create the animation
[UIView beginAnimations:nil context:nil];
// Create the delegate, so the "fromView" is removed after the transition
[UIView setAnimationDelegate: fromView];
[UIView setAnimationDidStopSelector:@selector(removeFromSuperview)];
// Set the transition duration
[UIView setAnimationDuration: 0.4];
// Add the "toView" as subview of "fromView" superview
[fromView.superview addSubview:toView];
switch (animation) {
case AnimationPushFromRigh:{
// Position the "toView" to the right corner of the page
toView.frame = CGRectOffset(pageFrame, pageWidth,0);
// Animate the "fromView" to the left corner of the page
fromView.frame = CGRectOffset(pageFrame, -pageWidth,0);
// Animate the "toView" to the center of the page
toView.frame = pageFrame;
// Animate the "fromView" alpha
fromView.alpha = 0;
// Set and animate the "toView" alpha
toView.alpha = 0;
toView.alpha = 1;
// Commit the animation
[UIView commitAnimations];
}
break;
case AnimationPushFromLeft:{
// Position the "toView" to the left corner of the page
toView.frame = CGRectOffset(pageFrame, -pageWidth,0);
// Animate the "fromView" to the right corner of the page
fromView.frame = CGRectOffset(pageFrame, pageWidth,0);
// Animate the "toView" to the center of the page
toView.frame = pageFrame;
// Animate the "fromView" alpha
fromView.alpha = 0;
// Set and animate the "toView" alpha
toView.alpha = 0;
toView.alpha = 1;
// Commit the animation
[UIView commitAnimations];
}
break;
default:
break;
}
}
我真的希望这有助于谁试图使用这种协调控制器模式:P