Oh cara, isso estava me causando dor de cabeça por alguns dias e não conseguia descobrir como fazer isso. A pior parte foi que a criação de um novo projeto iOS do Xcode com o modelo de detalhes mestre funcionou perfeitamente. Felizmente, no final, esse pequeno fato foi como eu encontrei a solução.
Existem alguns posts que eu achei que sugerem que a solução é implementar o novo primaryViewControllerForCollapsingSplitViewController:
método UISplitViewControllerDelegate
. Eu tentei isso sem sucesso. O que a Apple faz no modelo de detalhes mestres que parece funcionar é implementar o novo splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
método de delegação ( respire fundo para dizer tudo isso) (novamente UISplitViewControllerDelegate
). De acordo com os documentos , este método:
Solicita ao delegado que ajuste o controlador de exibição primário e incorpore o controlador de exibição secundário na interface recolhida.
Leia a parte da discussão desse método para obter detalhes mais específicos.
A maneira como a Apple lida com isso é:
- (BOOL)splitViewController:(UISplitViewController *)splitViewController
collapseSecondaryViewController:(UIViewController *)secondaryViewController
ontoPrimaryViewController:(UIViewController *)primaryViewController {
if ([secondaryViewController isKindOfClass:[UINavigationController class]]
&& [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]]
&& ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
// Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return YES;
} else {
return NO;
}
}
Essa implementação basicamente faz o seguinte:
- Se
secondaryViewController
é o que estamos esperando (a UINavigationController
) e está mostrando o que estamos esperando (a DetailViewController
- seu controlador de exibição), mas não tem modelo ( detailItem
), então " Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
"
- Caso contrário, retorne "
NO
para permitir que o controlador de exibição dividido tente incorporar o conteúdo do controlador de exibição secundário na interface recolhida"
Os resultados são os seguintes para o iPhone em retrato (iniciando em retrato ou girando para retrato - ou classe de tamanho mais compacta):
- Se sua visão estiver correta
- e tem um modelo, mostra o controlador de exibição de detalhes
- mas não tem modelo, mostre o controlador de visualização principal
- Se sua visão não estiver correta
- mostre o controlador da vista principal
Claro como lama.
UISplitViewController
e sempre volteiYES
desse método, depois mudei a classe de exibição dividida no Storyboard, pois sempre quero mostrar o mestre no iPhone em retrato. :)UISplitViewController
mas achei que isso não funcionava:splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
nunca foi chamado. Em vez disso, copiei o modelo da Apple e o coloquei no AppDelagate. Isso exigiu algumas alterações na criação do UISplitViewControllerapplication didFinishLaunchingWithOptions:
também (onde eu também copiei o modelo da Apple).splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
nunca é chamado. Parece que o delegado está sendo definido corretamente como oapplicationDidFinishLaunchingWithOptions:
método do delegado do meu aplicativo . Alguém já viu esse problema e NÃO teve essa solução funcionando?Aqui está a resposta aceita em Swift. Basta criar essa subclasse e atribuí-la ao seu splitViewController no seu storyboard.
fonte
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
Versão rápida da resposta correta de Mark S
Conforme fornecido pelo modelo Master-Detail da Apple.
Esclarecimento
(O que Mark S disse foi um pouco confuso)
Esse método delegado é chamado
splitViewController: collapseSecondaryViewController: ontoPrimaryViewController:
, porque é o que faz. Ao mudar para um tamanho de largura mais compacto (por exemplo, ao girar o telefone de paisagem para retrato), ele precisa recolher o controlador de exibição dividida em apenas um deles.Esta função retorna um booleano para decidir se deve recolher o detalhe e mostrar o mestre ou não.
Portanto, no nosso caso, decidiremos com base se houve um detalhe selecionado ou não. Como sabemos se nossos detalhes foram selecionados? Se seguirmos o modelo Master-Detail da Apple, o controlador de exibição de detalhes deve ter uma variável opcional com as informações detalhadas, portanto, se for nulo (.
É isso aí.
fonte
Apple's Master-Detail template
, não se destina a ser ótimo ou conciso, apenas factual. :)A partir da documentação , você precisa usar um representante para dizer para
UISplitViewController
não incorporar a exibição de detalhes na "interface recolhida" (por exemplo, o "modo Retrato" no seu caso). No Swift 4, o método delegado a ser implementado para isso foi renomeado:fonte
.m:
fonte
Meu aplicativo foi escrito no Swift 2.xe pode funcionar bem. Depois de convertê-lo no Swift 3.0 (usando o conversor XCode), ele começa a mostrar os detalhes primeiro, em vez de mestre no modo retrato. O problema é que o nome da função splitViewController não é alterado para corresponder ao novo UISplitViewControllerDelegate.
Depois de alterar o nome dessa função manualmente, meu aplicativo agora pode funcionar corretamente:
fonte
self.delegate = self
noviewDidLoad
método.Se você não tiver valores padrão para mostrar no controlador de exibição de detalhes, basta excluir as segue padrão entre o SplitViewController e seu UIViewController de detalhes no storyboard. Isso fará com que ele sempre entre primeiro no Master View Controller.
O efeito colateral disso é que, em vez de ver duas vistas em paisagem, você verá uma vista em tamanho real no SplitViewController até que Mostrar detalhe do segmento no controlador de vista principal seja acionado.
fonte
Para todas as pessoas que não conseguiram encontrar a seção sexta-feira do cs193p:
No Swift 3.1.1, criar uma subclasse de UISplitViewController e implementar um dos métodos delegados funcionou para mim como um encanto:
Meu storyboard
fonte
public func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool
Na minha opinião, você deve resolver esse problema de forma mais genérica. Você pode subclassificar o UISplitViewController e implementar um protocolo nos controladores de exibição incorporados.
Exemplo de implementação no UITableViewController:
Espero que ajude. Então você pode reutilizar essa classe e só precisa implementar um protocolo.
fonte
Apenas remova o DetailViewController dos controladores SplitView quando precisar iniciar a partir do Master.
fonte
Isso funcionou para mim no iOS-11 e Swift 4:
fonte
A função é renomeada em novas versões do Swift, portanto, este código funciona no Swift 4:
fonte
Solução Xamarin / C #
fonte
Basta definir a
preferredDisplayMode
propriedade deUISplitViewController
como.allVisible
fonte