在iOS 7 UIBarButtonItem外观麻烦,这可能是一个苹果的错误?

我回头看了一篇文章,这里是:

iOS 6中的用户界面自定义

它显示了iOS 6的自定义。由于我已经写了使用该技术的应用程序的文章,它非常简单,没有魔法。

但是,我需要更新我的应用程序之一,并在iOS 7下无法正常工作。 看来UIBarButtonItems的定制在第一次出现视图的时候不起作用。 如果我解雇了观点,然后呈现它一切正常。 这里显示的是:

第一次看到的是:

在这里输入图像说明

第二次:

在这里输入图像说明

我在他的例子中看到了这个问题,我的代码和我写的一个testing应用程序。 代码如下:

// Customizing the Back Bar Buttons UIImage * btBack_30 = [[UIImage imageNamed:@"btBack_30"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)]; UIImage * btBack_24 = [[UIImage imageNamed:@"btBack_24"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 5)]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_24 forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone]; 

正如你可以看到没有真正的魔法,很标准,但我找不到任何理由或解释为什么这不起作用的iOS 7中。代码得到执行- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

我希望有人看到这一点,可以提供一个解决scheme。 谢谢你的帮助!

**注意:有人build议,这不是一个苹果的错误,但通过devise。 我并不是说它是一个苹果问题,它可能更可能是我的,但是如果你运行任何一个样本或者复制并粘贴下面的代码,显然它第一次不能正常工作,并且随后发生。 这将导致我相信,API调用是有效的,但无论是他们有一个错误,或者我失去了一些需要做的事情。

****更新4:**

在我的示例中,我将MyAppDelegate的init方法中的代码更改为基于FruityGeek的build议,但仍然没有运气:

 - (instancetype)init { self = [super init]; if (self) { //Other UIAppearance proxy calls go here [[UIBarButtonItem appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: //[UIColor colorWithRed:220.0/255.0 green:104.0/255.0 blue:1.0/255.0 alpha:1.0], [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0], UITextAttributeTextColor, //[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0], [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8], UITextAttributeTextShadowColor, [NSValue valueWithUIOffset:UIOffsetMake(0.5, 0.5)], UITextAttributeTextShadowOffset, [UIFont systemFontOfSize:12.0], UITextAttributeFont, nil] forState:UIControlStateNormal]; // Customizing the Back Bar Buttons //ios6 uses whole button background image UIImage * btBack_30 = [[UIImage imageNamed:@"btBack_30"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)]; UIImage * btBack_24 = [[UIImage imageNamed:@"btBack_24"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 5)]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_24 forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone]; if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { //ios7 needs additional chevron replacement image UIImage * chevronReplacement = chevronReplacement = [btBack_30 imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; UIImage * chevronTransitionMaskReplacement = chevronTransitionMaskReplacement = [btBack_30 imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; [[UINavigationBar appearance] setBackIndicatorImage:chevronReplacement]; [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:chevronTransitionMaskReplacement]; } } return self; } 

****更新3:**

我已经添加了一个dropbox链接到一个示例项目。 这是除了上面已经发布的链接,这是一个简单的应用程序,也显示了这个问题。 两者都可以在iOS 6和iOS 7的模拟器中构build和运行。在iOS 6的情况下,一切正常。 在iOS 7中,如果您单击表格单元格并呈现下一个视图,则自定义后退button不会显示,如果您返回并再次显示该button,则会出现该button。

我一直在这个鬼混,所以我希望别人看到它,可以告诉我什么,我错过了。

https://www.dropbox.com/s/oi1bh3emvtbmms0/NavigationBarDemo.zip

这可能是愚蠢的,但它可能与我的图像? 我会尝试使用不同的图像的样本,并发布更新。

  • 尝试不同的图像,这没有什么区别,也使用上面张贴的示例图像。 这是一个远射,但由于似乎没有人有更好的主意,所以值得一试。

****更新2:**

我已经在另一个testing应用程序中尝试了这一点,并将代码移动到应用程序委托的初始化,它仍然无法正常工作。 我有这张贴在这里以及在顶部链接的原作者网站。 再加上另一个论坛,但没有人似乎有一个解决scheme。

我想知道如果这可能是一个苹果的错误?

****更新1:**

didFinishLaunchingWithOptions代码移到了willFinishLaunchingWithOptionsinit ,它仍然不起作用。

 ***** INIT METHOD FROM AppDelegate.m - (id)init { // Create resizable images UIImage *gradientImage44 = [[UIImage imageNamed:@"navBar_44"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; UIImage *gradientImage32 = [[UIImage imageNamed:@"navBar_32"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; // Set the background image for *all* UINavigationBars [[UINavigationBar appearance] setBackgroundImage:gradientImage44 forBarMetrics:UIBarMetricsDefault]; [[UINavigationBar appearance] setBackgroundImage:gradientImage32 forBarMetrics:UIBarMetricsLandscapePhone]; // Customize the title text for *all* UINavigationBars [[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0], UITextAttributeTextColor, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8], UITextAttributeTextShadowColor, [NSValue valueWithUIOffset:UIOffsetMake(1, 1)], UITextAttributeTextShadowOffset, [UIFont boldSystemFontOfSize:18.0], UITextAttributeFont, nil]]; // Customizing the NavBar Buttons UIImage * button30 = [[UIImage imageNamed:@"btButton_30"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)]; UIImage * button24 = [[UIImage imageNamed:@"btButton_24"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)]; [[UIBarButtonItem appearance] setBackgroundImage:button30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [[UIBarButtonItem appearance] setBackgroundImage:button24 forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone]; [[UIBarButtonItem appearance] setTintColor:[UIColor whiteColor]]; [[UIBarButtonItem appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: //[UIColor colorWithRed:220.0/255.0 green:104.0/255.0 blue:1.0/255.0 alpha:1.0], [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0], UITextAttributeTextColor, //[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0], [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8], UITextAttributeTextShadowColor, [NSValue valueWithUIOffset:UIOffsetMake(0.5, 0.5)], UITextAttributeTextShadowOffset, [UIFont systemFontOfSize:12.0], UITextAttributeFont, nil] forState:UIControlStateNormal]; // Customizing the Back Bar Buttons UIImage * btBack_30 = [[UIImage imageNamed:@"btBack_30"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)]; UIImage * btBack_24 = [[UIImage imageNamed:@"btBack_24"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 5)]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_24 forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone]; return [super init]; } 

它看起来像一个苹果的错误,你应该与错误记者input一个错误。 这就是说,我可以给你一个相对无痛的解决方法:将此代码添加到您的RecipetTableViewController:

 - (void)viewDidLoad { [super viewDidLoad]; self.title = @"Recipe Book"; UIBarButtonItem *it = [[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:NULL]; UIImage * btBack_30 = [[UIImage imageNamed:@"btBack_30"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)]; [it setBackButtonBackgroundImage:btBack_30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; self.navigationItem.backBarButtonItem = it; } 

编辑:你可以重复这个错误,如果感兴趣,更多的错误引用它更可能苹果将修复它:

错误:15506447

状态:OpenProduct:iOS版

19-Nov-2013 03:53 PM

简介:设置UIBarButtonItem外观代理的back barbutton项不会有任何影响,直到该button的第二次出现。

重现步骤:在appDelegate中,在任何事情出现之前,添加这些语句:

UIImage * gradientImage44 = [[UIImage imageNamed:@“navBar_44”] resizableImageWithCapInsets:UIEdgeInsetsMake(0,0,0,0)]; UIImage * gradientImage32 = [[UIImage imageNamed:@“navBar_32”] resizableImageWithCapInsets:UIEdgeInsetsMake(0,0,0,0)]; //设置所有 UINavigationBars的背景图像[[UINavigationBar appearance] setBackgroundImage:gradientImage44 forBarMetrics:UIBarMetricsDefault]; [UINavigationBar外观] setBackgroundImage:gradientImage32 forBarMetrics:UIBarMetricsLandscapePhone];

预期的结果:当一个viewController被第一次按下时,它的后退button中有图像。

实际结果:第一次出现,没有图像。 再次将视图推到那里。 实际上,当你第一次点击button时,确实会出现,但是当button第一次出现时不会出现。

版本:Xcode 5.0.1,iOS 7.0.3

注意:在导航控制器的根视图控制器中添加它会使其工作:

  • (void)viewDidLoad {[super viewDidLoad];

    self.title = @“食谱”; UIBarButtonItem * it = [[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:NULL]; UIImage * btBack_30 = [[UIImage imageNamed:@“btBack_30”] resizableImageWithCapInsets:UIEdgeInsetsMake(0,13,0,5)]; [itBackButtonBackgroundImage:btBack_30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; self.navigationItem.backBarButtonItem = it; }

附加演示项目显示问题。

组态:

附件:“DynamicsCatalog.zip”已成功上传。

编辑:我很高兴再次说,在错误记者进入错误,有时工作!

我试图改变你的演示项目中的一些东西,但正如你所说的没有任何工作。 我想也许这是因为UINavigationController子类,但使用标准的具有相同的行为。

不幸的是,如果你真的需要显示你的button,在启动时,我会默默地做开门closures的行为…抱歉的提议

你必须处理自定义iOS7的后退button项目。 在iOS6下,后退button是一个有边框的button,其中包含前一个屏幕的标题,并在整个button下扩展了背景图像。

在iOS7下,Back控件是一个V形图像加上前一个屏幕的标题。 如果要使用自定义图像replace默认V形图像,则还需要创build自定义蒙版图像。 iOS 7使用蒙版来使导航过渡期间,前一个屏幕的标题显示出来,或者消失在人字形中。

因为你在故事板中这样做,所以设置外观代理的最佳位置是在你的应用程序委托的init方法中。

 - (instancetype)init { self = [super init]; if (self) { //Other UIAppearance proxy calls go here // Customizing the Back Bar Buttons //ios6 uses whole button background image UIImage * btBack_30 = [[UIImage imageNamed:@"btBack_30"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 13, 0, 5)]; UIImage * btBack_24 = [[UIImage imageNamed:@"btBack_24"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 5)]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_30 forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [[UIBarButtonItem appearance] setBackButtonBackgroundImage:btBack_24 forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone]; if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { //ios7 needs additional chevron replacement image UIImage * chevronReplacement = nil; chevronReplacement = [chevronReplacement imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; UIImage * chevronTransitionMaskReplacement = nil; chevronTransitionMaskReplacement = [chevronTransitionMaskReplacement imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; [[UINavigationBar appearance] setBackIndicatorImage:chevronReplacement]; [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:chevronTransitionMaskReplacement]; } } return self; } 

我能够通过在视图的viewWillDisappear方法中执行后退button自定义来解决这个问题,该方法推送到我想要后退button的视图。 原因是因为前一个视图是“拥有”后退button,而不是当前视图。

 -(void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear: animated]; UIImage * backButtonImage = [[UIImage imageNamed:@"back.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(6, 15, 6, 7)]; UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:NULL]; [buttonItem setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; self.navigationItem.backBarButtonItem = buttonItem; } 

This is not the bug. This is default apple's iOS7 behavior.

有了iOS7的外观,你不需要设置背景。 虽然如果你想要,你可以使用自定义栏button到自定义导航栏来实现它。

享受编程!