4

Я создаю приложение iOS с большим количеством пользовательских представлений, поэтому использование стандартных представлений Cocoa не было вариантом. Затем я решил пойти с Контроллер-координатор/медиатор (изученный в Apress - Pro Objective-C Design Patterns для iOS).Координационный шаблон проектирования контроллера в Cocoa Touch

От делегата, я создаю 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; 
} 

В СИБ, я создал Obect (Координационный контроллер) я называю IBAction оттуда. Он работает очень хорошо, и я могу изменить свои взгляды (это все еще необходимо реализовать) .........

НО ... Я также хочу изменить язык, но, поскольку это не проблема навигации, я хочу сделать это из C6LanguageSettingsViewController, а не из C6CoodinatingController.

Итак, я создал еще один IBAction в C6LanguageSettingsViewController:

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

При подключении кнопки к этой IBAction (через владелец файла или через объект LanguageSettingsViewController), приложение ломает и, иногда он не показывает ошибки и иногда он представляет Непризнанный селектор, отправленный в пример ИЛИ EXC_BAD_ACCESS (код = 1, адрес = 0x .........) в UIApplicationMain.

Я считаю, что проблема заключается в том, что NIB не находит владельца файла ... но я не уверен, как его решить.

ответ

1

Хорошо ... это кажется абсурдным, но Я отвечаю себе: P

мне удалось заставить его работать, и я обнаружил, что я был управляющим viewControllers в BAAAAD образом, поэтому я изменил некоторые (, наконец!) код в координирующего управления:

во-первых, у меня нет "настоящего" mainViewController с NIBS и Stuf не более ...

OLD инициализировать

- (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, так что я могу выбрать правильный СИБ.

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: это владелец файла и координационный контроллер.

Другой BIG вещь об использовании такого рода шаблон, как переходить из одного вида в другой, не взрываются памяти устройства 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; 
    } 
} 

В начале метод, я много математики ... я «создал» шаблон, в котором каждый СИБ должен иметь это теги, начинающиеся с 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

Смежные вопросы