4

多くのカスタム ビューを使用して iOS アプリケーションを作成しているため、デフォルトの Cocoa ビューを使用することはできませんでした。次に、Coordinating / Mediator Controllerデザイン パターン (Apress - Pro Objective-C Design Patterns for iOS で学習) を使用することにしました。

デリゲートから、調整コントローラーのビューを指す 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];
}

最初のビューを選択するセレクターもあります (現時点では 2 つしかありません)。

-(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 を呼び出します。問題なく動作し、ビューを変更できます (まだ実装する必要があります)………</p>

しかし… 言語も変更したいのですが、ナビゲーションの問題ではないので、C6CoodinatingController からではなく、C6LanguageSettingsViewController から変更したいと考えています。

そこで、C6LanguageSettingsViewController に別の IBAction を作成しました。

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

ボタンをこの IBAction に接続すると (File's Owner または LanguageSettingsViewController オブジェクトを介して)、アプリが中断し、エラーが表示されない場合もあれば、認識されないセレクターがインスタンスに送信された、またはEXC_BAD_ACCESS (コード = 1、アドレス = 0x…)と表示される場合もあります。 ……) UIApplicationMain で。

問題は、NIB がファイルの所有者を見つけられないことだと思いますが、解決方法がわかりません。

4

1 に答える 1

1

わかりました…ばかげているようですが、私は自分自身に答えています:P

私はそれを機能させることができました(最終的に!)そして、viewControllersをBAAAADの方法で管理していることがわかったので、調整コントローラーのコードをいくつか変更しました:

まず、NIB を備えた「本物の」mainViewController がありません…</p>

古い初期化

- (void) initialize{
    C6Log(@"");
    [self checkDevice];
    _mainVC = [C6MainViewController initWithDevice:device];
    _activeVC = _mainVC;
    [self checkLanguage];
    [self chooseFirstView];
}

NEW 初期化

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

大きな変更点は、いつ、どのように _activeVC を開始したか、そして _languageVC と _accountVC の両方がグローバル変数になったことです。

これが変更された後、NIB ボタンは両方の IBAction メソッドを呼び出します。つまり、ファイルの所有者であり、調整するコントローラーです。

この種のパターンの使用に関するもう 1 つの重要な点は、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 で始まります……</p>

#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

于 2012-06-07T12:01:31.833 に答える