L'image d'arrière-plan personnalisée n'apparaissant pas au départ n'a pas été corrigée dans la version GM ou finale d'iOS7, pour autant que je sache. Je constate le même problème. Il semble qu'il s'agisse d'un bogue Apple ; la vue privée utilisée par Apple ne reçoit tout simplement pas d'appel setNeedsDisplay lorsqu'elle en a besoin lors de l'affichage initial. Si l'on fait quoi que ce soit qui provoque cet appel, cela devrait résoudre le problème -- comme appuyer dessus (ce qui change probablement l'état interne pour qu'elle appelle setNeedsDisplay sur elle-même), ou faire apparaître une modale (ce qui force probablement un réaffichage de toute la hiérarchie de la vue lors du prochain appel viewWillAppear :).
L'utilisation de leftBarItems à la place peut également fonctionner, mais cela peut causer beaucoup de problèmes de maintenance avec le code existant (certains écrans peuvent avoir leurs propres éléments de gauche, s'attendant à ce que lorsqu'ils sont remis à zéro, ils restaurent l'élément de gauche original, par exemple).
Comme indiqué, l'idéal serait de pouvoir passer à un aspect sans bordure sur iOS7, ce qui signifie que le bogue n'est pas vraiment apparent (puisqu'il n'y a pas d'image de fond). Cependant, dans certaines situations de transition iOS6/iOS7, cela peut s'avérer difficile (beaucoup d'écrans, et/ou la nécessité de supporter les anciennes versions d'iOS pendant un certain temps et trop difficile d'avoir deux looks implémentés, et cela ne rend pas bien sans bordure sans autres changements). Si c'est le cas, le patch suivant devrait fonctionner :
#import <objc/runtime.h>
@implementation UINavigationBar (BackButtonDisplayFix)
+ (void)load
{
if ([UIDevice currentDevice].systemVersion.intValue >= 7)
{
/*
* We first try to simply add an override version of didAddSubview: to the class. If it
* fails, that means that the class already has its own override implementation of the method
* (which we are expecting in this case), so use a method-swap version instead.
*/
Method didAddMethod = class_getInstanceMethod(self, @selector(_displaybugfixsuper_didAddSubview:));
if (!class_addMethod(self, @selector(didAddSubview:),
method_getImplementation(didAddMethod),
method_getTypeEncoding(didAddMethod)))
{
Method existMethod = class_getInstanceMethod(self, @selector(didAddSubview:));
Method replacement = class_getInstanceMethod(self, @selector(_displaybugfix_didAddSubview:));
method_exchangeImplementations(existMethod, replacement);
}
}
}
- (void)_displaybugfixsuper_didAddSubview:(UIView *)subview
{
[super didAddSubview:subview];
[subview setNeedsDisplay];
}
- (void)_displaybugfix_didAddSubview:(UIView *)subview
{
[self _displaybugfix_didAddSubview:subview]; // calls the existing method
[subview setNeedsDisplay];
}
@end
Remarque : UINavigationBar dispose actuellement d'une surcharge de la méthode en question. Je m'attendrais donc à ce que le style method_exchangeImplementations soit utilisé. J'ai juste ajouté les autres éléments par sécurité, au cas où Apple modifierait son code. Il se peut que nous passions nous-mêmes au borderless, mais j'ai trouvé que cette approche fonctionnait comme une option (jusqu'à une mise à jour plus complète de l'interface utilisateur), au moins.
Note supplémentaire : Ce bogue semble être corrigé dans iOS 7.1. Ainsi, le correctif pourrait être conditionné pour n'installer les méthodes que si vous utilisez >= 7.0 et < 7.1.