2010-05-13 4 views
1

У меня есть приложение MVC с одной моделью и несколькими видами (что-то вроде скинов). Я хочу, чтобы пользователь мог переключать представления, и я не могу заставить его работать с ориентацией интерфейса. Самый простой подход выглядит следующим образом:Переключение между несколькими видами при уважении ориентации

- (void) switchToADifferentView: (UIView*) newView { 
    // self is a descendant of UIViewController 
    self.view = newView; 
} 

Это не работает, потому что входящий вид не повернется в соответствии с текущей ориентацией (до следующего изменения ориентации, test case). Есть ли способ заставить ориентацию взгляда? Похоже, что система действительно пытается сохранить элементы управления интерфейсом для себя. (Или это так же просто, как установить правильное преобразование вручную?)

Я решил, что лучше не переключать виды напрямую и вместо этого переключаться контроллерами. Это имеет смысл, поскольку упрощает первоначальный код. Но как переключить контроллеры, у которых нет «навигационного отношения» между ними? Думаю, я мог бы использовать presentModalViewController:, но это похоже на взломать. То же самое касается навигационного контроллера. Если бы я поменять контроллеры вручную, я получаю неправильную ориентацию снова:

- (void) switchToAController: (id) incoming { 
    [currentController.view removeFromSuperview]; 
    [window addSubview:incoming.view]; // does not respect current orientation 
} 

Теперь как щеколда я просто заменить существующий контроллер для другого? Опять же, контроллеры - это что-то вроде «скинов», работающих над общей моделью, поэтому нет смысла делать вид, что кожа A является «модальным» диалогом над кожей B или что они являются частью стека навигации.

ответ

0

В конце концов я пошел с подходом «батут». Каждый «скин» представляет собой отдельный контроллер, и есть специальный корневой контроллер, который представляет скины как модальные контроллеры. Когда скин хочет переключиться на другой, он устанавливает флаг, указывающий желаемый следующий скин, и увольняет себя. Корневой контроллер просыпается (viewWillAppear), замечает флаг и отображает следующий скин.

Это решение имеет два основных преимущества: 1] Код контроллера остается простым, так как каждый контроллер отображает один и только вид, без переключения вида. 2] Нет необходимости взламывать код ориентации, так как ориентация изображения внутри модно отображаемых контроллеров обрабатывается системой прозрачно.

1

При переключении с видом непосредственно с использованием первого образца кода ориентация может быть фиксированной установкой преобразования вручную:

- (CGAffineTransform) transformForOrientation: (UIInterfaceOrientation) io 
{ 
    NSParameterAssert(io <= 4); 
    // unknown, portrait, portrait u/d, landscape L, landscape R 
    float angles[] = {0, 0, M_PI, M_PI/2, -M_PI/2}; 
    return CGAffineTransformMakeRotation(angles[io]); 
} 

- (void) switchToView: (UIView*) newView 
{ 
    newView.transform = [self transformForOrientation:self.interfaceOrientation]; 
    self.view = newView; 
} 

Кроме того, если вы хотите обменяться мнениями во время вращения, все становится еще сложнее. Сначала вам нужно преобразовать входящий вид в соответствии с текущим. Это должно быть сделано в willRotate… обратного вызова:

- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) target 
     duration: (NSTimeInterval) duration 
{ 
    incomingView = [[UIView alloc] init…]; 
    incomingView.transform = self.view.transform; 
} 

И затем вы переключаетесь мнения в willAnimate… обратного вызова и установить преобразование в соответствии с целевой ориентацией:

- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) io 
     duration: (NSTimeInterval) duration 
{ 
    incomingView.transform = [self transformForOrientation:io]; 
    self.view = incomingView; 
} 

Таким образом, новый вид заменяет текущий и плавно поворачивается в целевое положение.

+0

Есть ли какие-либо ref-документы о необходимости преобразования ориентации вида вручную? –