iPhone: Na paisagem somente, após a primeira addSubview, UITableViewController não rodar corretamente

StackOverflow https://stackoverflow.com/questions/1632117

  •  06-07-2019
  •  | 
  •  

Pergunta

Um projeto Xcode ilustrativo mínima para isso está disponível em github .

No meu UIWindow, quando eu adiciono segunda (e subseqüente) UITableView de como subviews, eles não rodam corretamente, e, assim, aparecer de lado. Isto só é testado no simulador. Aqui está um código pouco para você:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    ShellTVC* viewA = [[ShellTVC alloc] initWithTitle:@"View A"];
    ShellTVC* viewB = [[ShellTVC alloc] initWithTitle:@"View B"];

    // The first subview added will rotate to landscape correctly. 
    // Any subsequent subview added will not.

    // You may try this by various commentings and rearranging of these two statements.

    [window addSubview:[viewA tableView]];
    [window addSubview:[viewB tableView]];

    [window makeKeyAndVisible];
}

viewB aparece lateralmente. Comente a addSubview para viewB e viewA aparece corretamente. Do que, para viewA apenas, e viewB aparece corretamente.

Eu não estou criando esses UITableViewControllers via ENE, embora o UIWindow é.

Caso você esteja se perguntando, ShellTVC é-a UITableViewController, e implementa este método:

- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

Além disso, tenho definir o UIInterfaceOrientation no arquivo plist para UIInterfaceOrientationLandscapeLeft.

Provavelmente relacionado - e sem resposta - SO perguntas aqui e aqui .

Foi útil?

Solução

Eu acho que descobri uma maneira - possivelmente o caminho certo - para fazer isso.

  1. Criar uma subclasse "mestre" UIViewController, que implementa shouldAutorotate ..., e adicione como o único ponto de vista sobre a sua janela.
  2. Para alternar entre viewA ou viewB, usar a combinação de dismissModalViewControllerAnimated: & presentModalViewController: animado: nesta vista controlador mestre.

Aqui está algum código:

// this doesn't really do much but implement shouldAutorotate...
@interface MasterViewController : UIViewController
@end

@implementation MasterViewController
- (BOOL) shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation {
     return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
@end

@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
    MasterViewController* masterVC;
    UIViewController* activeTVC;
    UIViewController* onDeckTVC;
}
@end

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    UIViewController* masterVC = [[MasterViewController alloc] init];        
    activeTVC = [[ShellTVC alloc] initWithTitle:@"View A"];
    onDeckTVC = [[ShellTVC alloc] initWithTitle:@"View B"];
    [window addSubview:masterView.view];
    [window makeKeyAndVisible];
    [masterVC presentModalViewController:activeTVC animated:NO];
}

// you would call this to toggle between "View A" and "View B"
- (void)toggleTVC {
    UITableViewController *hold = activeTVC;
    activeTVC = onDeckTVC;
    onDeckTVC = hold;
    [masterVC dismissModalViewControllerAnimated:NO];   
    [masterVC presentModalViewController:activeTVC animated:NO];
}

Por que isso funciona?

  1. Todas as alterações de orientação fluir através de controladores de vista, não vistas.

  2. Tanto quanto eu posso dizer, a primeira vista ou subexibição que você adicionar à sua janela fica um pouco de molho especial. Se esse ponto de vista tem um controlador de vista, a janela de figuras-lo.

Isto é, para apenas o primeiro subexibição, você pode pensar este código:

[window addSubview:masterVC.view];

como fazer algo assim (não é um método real!):

[window addSubview:masterVC.view withViewController:masterVC];

Eu não entendo mais nada sobre isso do que isso. Acho que o fato de que eu posso fazer isso com o primeiro subexibição, mas não outros, extremamente desconcertante. Mais informações boas-vindas, e por favor deixe-me saber se isso te ajudou ou não.

Outras dicas

Aparentemente, se você adicionar vista como uma criança de pontos de vista que será rodado corretamente. Esta não é uma grande solução para o meu projeto, mas parece que ele pode ser a única solução.

Infelizmente seus subviews só são perguntado sobre o que orientações que suportam quando uma mudança na orientação ocorre.

Assim que eu acabar definindo a orientação antes de eu empurrar o novo controlador de vista na pilha se eu sei que mudou:

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 

Sim, esta é uma chamada não suportado.

Você pode usar o objeto UIApplication para forçar uma orientação do dispositivo particular.

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];

Sim, eu acredito que você tem que resolver esta questão por ter múltiplos XIB. Eu lembro de ter visto esta solução através de um dos livros que li no passado. Se não, você tem jogo com tradução ea posição do objeto na vista ... melhor ter XIB separado.

Isso deve funcionar.

- (void)viewDidLoad {
    if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) || 
        ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)) 

    {
        self.view.frame = CGRectMake(0, 0, 1024, 748);

    } else {
        self.view.frame = CGRectMake(0, 0, 768, 1004);
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top