Cocoa Touch中的协调控制器设计模式 [英] Coordinating Controller design pattern in Cocoa Touch

查看:161
本文介绍了Cocoa Touch中的协调控制器设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建具有大量自定义视图的iOS应用程序,因此,使用默认的Cocoa视图不是一个选项。然后,我决定使用协调/调解员控制器设计模式(在Apress的Pro Objective-C设计模式iOS中学习)。

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).

从委托中,我创建一个指向我协调控制器视图的rootViewController:

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];
}
}

然后,我有一个IBAction被我的视图:

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;
}

在NIB中,我创建了一个Obect(协调控制器),我称之为IBAction从那里。它工作得很好,我可以改变我的意见(它仍然需要实现).........

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)………

但是我也想改变语言,但是,因为它不是一个导航问题,我想从C6LanguageSettingsViewController中执行,而不是从C6CoodinatingController执行。

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.

所以,我在C6LanguageSettingsViewController中创建了另一个IBAction:

So, I created another IBAction in the C6LanguageSettingsViewController:

- (IBAction)chooseLang:(id)sender{
UIImage *bt;
[self resetImagesToNormalState];
C6Log(@""); 
C6Log(@"%@", [sender tag]);
C6Log(@"%@", sender);
.
.
.


$ b有时它显示没有错误,有时它会在UIApplicationMain中显示发送到实例或 EXC_BAD_ACCESS(Code = 1,address = 0x .........)的无法识别的选择器。

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.

我相信问题是NIB没有找到文件的所有者...但我不知道如何解决它。

I believe the problem is the NIB doesn't find the file's owner… but I'm not sure how to solve it.

推荐答案

好吧,这似乎是荒谬的,但我在回答自己:P

Ok… it seems absurd, but I'm answering myself :P

我设法使工作(finaly!),我发现我正在以BAAAAD方式管理viewController,所以我改变了协调控制器中的一些代码:

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:

首先,我不有一个真正的mainViewController与NIB和stuf没有更多...

First, I don't have a "real" mainViewController with NIBs and stuf no more…

旧初始化

- (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。

checkDevice verifies if it's iPhone or iPad, so I can choose the right NIB.

checkLanguage 检查[NSUserDefaults standardUserDefaults]的语言

checkLanguage checks the [NSUserDefaults standardUserDefaults] for the language

Finaly,我叫selectFirstView:

Finaly, I call 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];
    }
}

新的selectFirstView p>

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现在都是全局变量的事实。

The big change is WHEN and HOW I initiated the _activeVC… AND the fact that both _languageVC and _accountVC are now global variables.

嗯,这个改变之后,NIB按钮调用了IBAction方法:它是文件的所有者和协调控制器

Well, after this changes, the NIB button call both IBAction methods: it's file's owner and the coordinating controller.

使用这种模式的另一个重要事情是如何从一个视图切换到另一个视图,而不会发生爆炸性的iOS设备内存...这里是如何在协调控制器内进行的:

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:

- (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 .........

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………

#define divisor         100
#define LanguageTags    0
#define AccountTags     1

然后,我从一个视图更改为另一个视图的方式就在那里:

Then, the way I change from one view to another is right there:

-(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

I really hope this helps who's trying to use this coordinating controller pattern :P

这篇关于Cocoa Touch中的协调控制器设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆