web-dev-qa-db-fra.com

iOS 11 préfère que les grands titres ne soient pas mis à jour jusqu'au défilement

J'ai implémenté un UIViewController de base avec un UITableView encapsulé dans un UINavigationController. J'ai mis prefersLargeTitles à true:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    navigationController?.navigationBar.prefersLargeTitles = true
    navigationItem.title = "Coffees"
}

Cependant, le titre reste petit jusqu'à ce que je fasse défiler la vue, puis l'élargit. J'ai essayé de déplacer cet appel à l'endroit où je crée UINavigationController, mais cela n'a eu aucun effet. Je suis sûr que le contrôle de navigation n’est pas à zéro lorsque j’ai défini prefersLargeTitles.

Devrais-je mettre à jour cette propriété ailleurs? Ou devrais-je déposer un radar?

Mettre à jour:

Cela ne semble se produire que si ma vue contient une UITableView ou est elle-même une UITableViewController

20
John Breen

J'ai eu le même problème. Bien que vous n'utilisiez pas de Storyboards, j'espère que cela pourrait aider quelqu'un. J'ai coché "Préférer les grands titres" pour le contrôleur de navigation (et non le contrôleur de vue) dans lequel j'ai intégré mon contrôleur ViewView. Tous les contrôleurs de vue après que le contrôleur de navigation ait tourné et avait de gros titres, et cela devrait fonctionner. 

 

16
Paco Wong

J'ai eu le même problème que sur une tableview ... 

Je devais mettre:

self.tableView.contentInsetAdjustmentBehavior = .never

de sorte que ma vue de table cesse de défiler lorsque uiviewcontroller est chargé.

C'est le défilement automatique de la table qui fait que le gros titre est masqué

J'espère que cela t'aides

7
user1523505

La modification de contentInset de tableView avec top:1 force la barre de navigation à se développer et à afficher les gros titres.

Obj-C

-(void) viewWillAppear:(BOOL)animated {
    if (@available(iOS 11.0, *)) {
        tableView.contentInset = UIEdgeInsetsMake(1, 0, 0, 0);
    }
}

Rapide

override func viewWillAppear(_ animated: Bool) {
    if #available(iOS 11.0, *) {
        tableView.contentInset = UIEdgeInsetsMake(1, 0, 0, 0)
    }
}

Remarque: Si vous avez une tableView.reloadData() dans votre viewWillAppear, assurez-vous de l'appeler après avoir modifié la contentInset

3
Pau Senabre

Je viens d'avoir le même problème et, dans mon cas, il s'avère que la structure Storyboard qui fonctionnait dans iOS 10 avec Swift 3 (et fonctionne également avec iOS 11 avec Swift 3) était à l'origine du problème sur iOS 11 avec Swift 4.

Élaborer:

J'avais un UIViewController normal dans mon storyboard que j'avais défini sur une sous-classe UINavigationController (ma hiérarchie est similaire à la vôtre, avec la sous-classe UITabBarController → la sous-classe UINavigationController → la sous-classe UITableView.

Dans iOS 10, cela a bien fonctionné.

Dans iOS 11, cela fonctionne également bien lorsque vous exécutez l'application Swift 3 existante.

Cependant, avec l'application Swift 4, fonctionnant sur iOS 11, je voyais les mêmes problèmes que vous avez décrits (les gros titres n'apparaissent que lorsque vous déroulez/faites défiler la vue).

Pour résoudre ce problème, j'ai remplacé les éléments basés sur UIViewController dans le Storyboard par des occurrences réelles d'UINavigationController (qui contiennent explicitement un UINavigationBar dans le Storyboard. J'ai l'intuition que le nœud du problème provient de ce que les instances d'UIViewController n'avaient cet élément explicitement déclaré dans le Storyboard).

Quoi qu'il en soit, cela a résolu le problème pour moi.

Je vais enregistrer le radar car cela ressemble à une régression basée sur Swift 4, car pour moi, cela fonctionne à la fois sous iOS 10 avec Swift 3 et sous iOS 11 avec Swift 3.

1
Aral Balkan

Le changement général du comportement de la navigationBar doit être fait en viewWillAppear(_:) 

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.prefersLargeTitles = true
}

Après cela, cela a bien fonctionné pour moi.

1
BilalReffas

Dans mon cas, la solution consistait à définir l'alignement supérieur de tableView sur Zone sécurisée et non sur Superview.

1
Arnaud Dorgans

Dans le storyboard, je règle Large Title de l'élément de navigation sur Never.

Navigation Item

Dans la méthode viewDidLoad de mon ViewController, je définis ce qui suit:

navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always
1
assb10yr

J’ai rencontré le même problème et découvert qu’il était généralement préférable de définir la propriété prefersLargeTitles à partir du contrôleur de vue ou de l’objet qui le configure et de le faire avant sa présentation.

Par exemple, si le contrôleur de vue en question est affiché au lancement de l'application:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    let window = UIWindow(frame: UIScreen.main.bounds)

    let someViewController: UIViewController = CustomViewController()

    let theNavController = UINavigationController(rootViewController: someViewController)
    theNavController.navigationBar.prefersLargeTitles = true

    window.rootViewController = theNavController
    window.makeKeyAndVisible()

    return true
}

ou si vous présentez un contrôleur de vue particulier:

let someViewController: UIViewController = CustomViewController()

let theNavController = UINavigationController(rootViewController: someViewController)
theNavController.navigationBar.prefersLargeTitles = true

present(theNavController, animated: true, completion: nil)

J'ai trouvé que cette méthode était un moyen plus sûr de s'assurer que le titre de la navigation est affiché en conséquence. J'espère que cela t'aides! :)

1
gomollon

J'ai résolu ce problème via le storyboard

  1. Contrôleur de navigation -> Barre de navigation -> Inspecteur d’attributs -> Préfère les grands titres
  2. Afficher le contrôleur -> Élément de navigation -> Inspecteur d'attributs -> Titre large (automatique ou toujours coché)
1
yoAlex5

Problème similaire pour moi avec un UITableViewController ajouté à un UIViewController. Dans mon cas, ces contrôleurs de vue sont eux-mêmes incorporés dans une UITabBarController et seul le premier onglet affiché utilisait correctement un grand titre. Les autres onglets nécessitaient un défilement manuel avant l'affichage du titre de grande taille.

La seule chose que je pouvais faire au travail était d’ajuster la contentInset selon la réponse de @pau-senabre, sauf que la top ne me servait à rien. Au lieu de cela, j'ai défini l'insertion left, puis je l'ai réinitialisé lors du prochain cycle d'exécution.

private var isFirstAppearance = true

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if isFirstAppearance {
        applyLargeTitlesFix()
    }
}

private func applyLargeTitlesFix() {
    let originalInset = tableViewController.tableView.contentInset
    tableViewController.tableView.contentInset = UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 0)
    DispatchQueue.main.async { [weak self] in
        self?.tableViewController.tableView.contentInset = originalInset
    }
    isFirstAppearance = false
}
0
Ben Packard

J'ai eu le même problème. La vue est une vue de table. La propriété de prefersLargeTitles est définie sur viewDidLoad event. Ensuite, j'ai défini le titre de la vue dans l'événement viewWillAppear.

override open func viewDidLoad() {
   if #available(iOS 11.0, *) {
        self.navigationController?.navigationBar.prefersLargeTitles = true
    } else {
        // Fallback on earlier versions
    }
    ...
}

override open func viewWillAppear(_ animated: Bool) {
    self.navigationItem.title = "something"
    ...
}

Dans mon événement prepare segue, j’ai défini la vignette de l’élément de navigation sur nil de sorte que l’élément de navigation à gauche suivant de la vue suivante affiche «Retour» automatiquement.

override func prepare(for segue: UIStoryboardSegue,
                      sender: Any?) {
    self.navigationItem.title = nil
    ...
}

La première fois que la vue tabulaire affiche un grand titre correctement. Cependant, si je sélectionne une ligne dans la vue suivante et revient à la vue sous forme de tableau, le titre de l'élément de navigation devient vide.

Après plusieurs heures de lutte, je découvre enfin que le titre de la vue doit être défini dans l'événement viewDidAppear! Il semble que tout ce qui est défini pour afficher le titre de la vue dans l'événement Will serait réinitialisé en interne par UIKit à nouveau à zéro. Donc, il doit être réglé dans un autre événement.

override func viewDidAppear(_ animated: Bool) {
   self.navigationItem.title = "something"
   ...
}

override open func viewWillAppear(_ animated: Bool) {
    // self.navigationItem.title = "something" // Remove it and set title in Did event!
    ...
}

Avant d’introduire cette nouvelle fonctionnalité iOS 11, mon application fonctionne correctement. Il semble que la nouvelle fonctionnalité comporte quelques modifications dans UIKit, de sorte que la version précédente de l'application peut nécessiter des mises à jour/modifications pour la rendre opérationnelle.

0
David.Chu.ca

Cela semble être un comportement étrange au début, mais essayez de régler le navigationItem.largeTitleDisplayMode sur always. La valeur par défaut est automatic - et la manière dont cela fonctionne dans docs n'est pas définie.

Également écrit/mettra à jour une réponse à propos des gros titres ici .

0
kgaidis

J'avais le même problème et je l'ai corrigé en modifiant l'ordre des vues dans ViewController dans InterfaceBuilder. 

Il semble que si la première vue dans la hiérarchie n'est PAS une vue de défilement, alors NavigationBar apparaît en mode Large Titre et ne s'anime pas avec la vue de défilement. Si vous avez besoin que le titre de la barre de navigation reflète votre défilement, vous devez placer la vue de défilement en premier dans la hiérarchie. 

De plus, je ne suis pas tout à fait sûr à ce sujet, mais l'apparence de la barre de navigation en mode Titre standard ou Titre large dépend de la hiérarchie des vues du contrôleur précédent. 

0
egor

J'ai récemment abordé le même problème et aucune des suggestions n'a fonctionné pour moi. Au lieu de cela, tout ce que j'avais à faire était d'invoquer sizeToFit(). Exemple de code:

private func configureNavigator() {
    guard let navigationController = navigationController else { return }
    navigationController.navigationBar.prefersLargeTitles = true
    navigationItem.largeTitleDisplayMode = .automatic
    navigationController.navigationBar.sizeToFit()
}

J'espère que ça aide!

0
titusmagnus

Une autre solution possible consiste à mettre fin à l'actualisation dans votre refreshHandler (). comme ça-

@objc func refreshPage() {
    self.refreshControl?.endRefreshing() //End here
    self.loadTableData() //Get fresh data and reload table
}
0
ManjunathK

J'ai perdu beaucoup de temps à ce sujet, car la saga prefersLargeTitle fonctionne sur certains contrôleurs de vue comme prévu et avec certains, elle produit le même problème que ci-dessus. 

La solution pour moi était de décocher Extended Edges Under Top Bar dans IB - pour les contrôleurs de vue qui affichent momentanément les gros titres jusqu'à ce que le contenu de la vue tableau soit chargé, puis la barre de navigation revient à la taille normale. Il ne montre que le gros titre lorsque vous faites défiler la vue tableau vers le bas.

Ceci est rétro-compatible avec iOS 10 et ne laisse aucun espace vide au-dessus de la première ligne de la vue tableau.

J'avais vérifié prefersLargeTitle dans l'inspecteur des attributs des contrôleurs de navigation uniquement dans IB - rien dans le code. Idem pour largeTitleDisplayMode = .always

Quant à savoir pourquoi cela se produit avec certains contrôleurs de vue et pas d'autres, je n'en ai aucune idée!

0
Ahmed Khedr

Programmation:

  1. Dans AppDelegate.Swift:

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()
    
    let navigationController = UINavigationController.init(rootViewController: ViewController())
    window?.rootViewController = navigationController
    
  2. Dans ViewController:

    remplacer func viewWillAppear (_ animé: Bool) {super.viewWillAppear (animé)

    navigationController?.navigationBar.prefersLargeTitles = true
    navigationItem.largeTitleDisplayMode = .automatic
    

    }

    remplacer func loadView () {super.loadView ()

    view.addSubview(tableView)
    view.addSubview(loadingView)
    
    NSLayoutConstraint.activate([
        tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
        tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        tableView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor),
        tableView.heightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.heightAnchor)
        ])
    

    }

VÉRIFIEZ QUE VOTRE VUE À TABLE A ÉTÉ AJOUTÉE À VOTRE VUE _ AT FIRST!

0

Même problème ici avec Swift 4.2, iOS 12 et les Storyboards refactorisés. 

J'ai essayé d'ajouter prefersLargeTitles = true à viewWillAppear et viewDidLoad, mais ni l'un ni l'autre n'a résolu le problème.

Au lieu de cela, j'ai copié les story-boards refactorisés dans main.storyboard et trouvé l'option d'activer les gros titres dans IB. Définissez cette option, puis refactorisez les storyboards et tout fonctionne maintenant. Pour une raison quelconque, la refactorisation initiale a supprimé l'option et je ne pouvais pas l'activer par programme.

0
Rami