【问题标题】:Why would this code work on iPhone 5, 4 and 4s but not 5s?为什么此代码适用于 iPhone 5、4 和 4s 而不是 5s?
【发布时间】:2014-04-01 16:31:00
【问题描述】:

我有下面的代码来添加一些UIBarButtons 到我的项目中。这适用于以下情况:

全部在 iOS 7.1 上

  • 模拟器 iPhone Retina 3.5 英寸;
  • 模拟器 iPhone 视网膜 4 英寸;
  • 模拟器 iPhone Retina 4 英寸(64 位)
  • iPhone 4
  • iPhone 4s

不过,我没有要测试的 iPhone 5 设备。

它不适用于新的 iPhone 5s。有什么不同?

代码如下:

    -(void)setupNavigationBar
{
    self.saveSearchButton =  [UIButton buttonWithType:UIButtonTypeCustom];
    [self.saveSearchButton setImage:[UIImage imageNamed:@"Save Search"] forState:UIControlStateNormal];
    [self.saveSearchButton setImage:[UIImage imageNamed:@"Save Search Active"] forState:UIControlStateHighlighted|UIControlStateSelected];
    [self.saveSearchButton addTarget:self action:@selector(saveSearchButtonpressed)forControlEvents:UIControlEventTouchUpInside];
    [self.saveSearchButton setFrame:CGRectMake(0, 0, 23, 31)];

     self.changeLayutButton =  [UIButton buttonWithType:UIButtonTypeCustom];
    [self.changeLayutButton setImage:[UIImage imageNamed:@"View List"] forState:UIControlStateNormal];
    [self.changeLayutButton setImage:[UIImage imageNamed:@"View Grid"] forState:UIControlStateHighlighted|UIControlStateSelected];
    [self.changeLayutButton addTarget:self action:@selector(changeViewLayoutButtonPressed)forControlEvents:UIControlEventTouchUpInside];
    [self.changeLayutButton setFrame:CGRectMake(0, 0, 23, 31)];

    self.sortByButton =  [UIButton buttonWithType:UIButtonTypeCustom];
    [self.sortByButton setImage:[UIImage imageNamed:@"Sort By"] forState:UIControlStateNormal];
    [self.sortByButton setImage:[UIImage imageNamed:@"Sort By Active"] forState:UIControlStateHighlighted|UIControlStateSelected];
    [self.sortByButton addTarget:self action:@selector(sortByButtonPressed)forControlEvents:UIControlEventTouchUpInside];
    [self.sortByButton setFrame:CGRectMake(0, 0, 23, 31)];

    UIBarButtonItem *fixedItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
    fixedItem.width = 20;

    UIBarButtonItem *saveSearchButton = [[UIBarButtonItem alloc] initWithCustomView:self.saveSearchButton];
    UIBarButtonItem *changeViewButton = [[UIBarButtonItem alloc] initWithCustomView:self.changeLayutButton];
    UIBarButtonItem *sortByButton = [[UIBarButtonItem alloc] initWithCustomView:self.sortByButton];


    NSArray *barbuttonitems = @[sortByButton, fixedItem, changeViewButton, fixedItem,saveSearchButton];

    self.navigationItem.rightBarButtonItems = barbuttonitems;

    self.lastLayoutUsed = [[NSUserDefaults standardUserDefaults]objectForKey:@"LastLayoutUsed"];

    if ([self.lastLayoutUsed isEqualToString:@"GridLayout"]){
        self.changeLayutButton.selected = YES;
        [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(highlightButton:) userInfo:self.changeLayutButton repeats:NO];
    }
}

我已经单步执行了代码,所有属性都不是 nil 并且具有有效值。我也检查了所有图像都是正确的一面。

这将如何在模拟器上的每台设备上运行,而不是在实际的 iPhone 5S 上运行?

另外,由于这两款手机(iPhone 4S 和 5S)的屏幕宽度和 iOS 版本完全相同,我真的很困惑吗?

按钮根本不显示。没有编译器警告,也没有控制台错误。

更新

在 iPhone 5 上测试了上面的代码,它工作得很好。这让人相信它一定与 iPhone 5S 的 64 位有关?

更新 2

从方法中删除所有代码并将其更改为一个非常简单的按钮,如下所示:

         self.saveSearchButton =  [UIButton buttonWithType:UIButtonTypeCustom];
[self.saveSearchButton setTitle:@"Save" forState:UIControlStateNormal];
    [self.saveSearchButton setTintColor:[UIColor blueColor]];
    UIBarButtonItem *saveSearchButton = [[UIBarButtonItem alloc] initWithCustomView:self.saveSearchButton];
    self.navigationItem.rightBarButtonItem = saveSearchButton;

这现在不适用于任何设备或模拟器。

我在这里做错了什么?

更新 3 - 解决方案!

是的,所以这只是一件简单的事情引起了所有这些大惊小怪。我将我的 UIButtons 声明为 weak 而不是 strong - 我的印象是 UI 元素需要很弱,因为它们经常离开视图?

我在 cmets 部分的帮助下得出了这个答案。

这也没有解释为什么它在声明为weak 时可以在 iPhone 4S 和 iPhone 5 上运行。它也适用于声明为 weak 的 64 位模拟器

这是否意味着将使用 64 位模拟器作为指导,并且必须在设备上进行实际测试,因为在 UIKit 测试时模拟器似乎不准确?

我很想了解更多关于这方面的信息。

【问题讨论】:

  • 请解释其中哪一部分不起作用。它是否显示任何内容,任何错误?..
  • 对不起,应该已经很清楚了。按钮根本不显示。没有编译器警告也没有控制台警告。
  • “这将如何在模拟器上的每台设备上运行,而不是在实际的 iPhone 5S 上运行?”无论如何,模拟器都不是完美的。
  • 我开始越来越意识到这一点。现在将所有 UI 测试转移到实际设备上。
  • 在黑暗中拍摄,但是您是否尝试过在需要的地方使用双精度/浮点数,例如此处 CGRectMake(0, 0, 23, 31) -> CGRectMake(0.0, 0.0, 23.0, 31.0) ?

标签: ios iphone objective-c


【解决方案1】:

问题在于[UIButton buttonWithType:UIButtonTypeCustom] 没有留下苹果文档中所述的对象实例。 UIBarButton 需要某种类型的实例。 https://developer.apple.com/library/ios/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html

AppleDocs 中所述的解决方案是使用 alloc+init 构造来制作按钮。

buttonWithType:

"这个方法是一个方便的构造函数,用于创建按钮对象 具有特定配置。如果你继承 UIButton,这个方法 不返回您的子类的实例。如果你想创建一个 特定子类的实例,您必须分配/初始化按钮 直接。”

【讨论】:

  • 我完全同意你的观点,按钮对象的实例确实需要buttonType:... 但这告诉我,如果缺少它,它不应该在任何设备上工作,这不是特定的对于 iPhone 5s 设备,这将是一个 iOS 问题。
  • 显然,Apple 原谅了程序员过去使用这种结构。但在 iPhone5S 等较新的设备上,他们采用了更严格的方式。为什么以及如何?只有苹果知道。他们让我们知道吗?不,至少不是清楚而直接。我们必须处理他们的运作方式,我们唯一能做的就是准确地阅读 AppleDocs。
  • 问题是它不是设备的东西,它是 iOS 的东西,无论我错过或做过[[UIButton alloc] init],我总是不得不把它放在上面,但无论如何它都不会工作设备或 iOS。您是否有任何文件表明这已根据设备而不是 iOS 变得更加严格???
  • 这是我根据我的问题和经验做出的假设。无论如何,这个问题的解决方案是他拥有的弱引用以及 buttonWithType: 没有留下任何实例的事实。这确实意味着引用计数根本不会增加,并且一旦引用离开声明它的函数的范围,按钮就会被取消。但是根据这个问题中的陈述,这适用于旧设备,所以这意味着必须在 ARC(如果他使用它)或 initWithCustomView: 的工作方式中进行更改。我找不到确凿的证据。所以这都是假设。
  • buttonWithType:UIButtonTypeCustom 不会创建 UIButton 子类。这个答案在这里不正确。请参阅下面的 Brian Slick 的回答。据我所知,在这种情况下,最终的解决方法应该是将 UIButtons 声明为 strong。如果我错了,请纠正我。
【解决方案2】:

@TotumusMaximus 您误解了文档的内容。注意第一部分:

如果你子类化 UIButton...

这意味着如果您尝试执行[MyAwesomeButton buttonWithType:UIButtonTypeCustom],将创建的对象将是 UIButton 实例,而不是 MyAwesomeButton 实例。为了获得 MyAwesomeButton 实例,您需要执行 [[MyAwesomeButton alloc] init]。 OP 的问题不涉及按钮子类,因此这部分文档不适用于此处。

【讨论】:

  • 我得出了同样令人困惑的结论。我对自己说,buttonWithType 不会创建子类。因此,投票的答案是不正确的。这是否意味着真正的解决方案是给这些 UIButtons 强引用并完成它?
【解决方案3】:

如果您的属性很弱,并且您直接将新创建的对象分配给它们,那么根据 ARC 的规则,它们应该立即被释放并设置为 nil,因为没有其他东西具有强引用给他们。在其他设备/模拟器上工作的事实是实施的意外。

现在没有必要为 UI 元素使用弱属性,因为视图不再在内存压力条件下被卸载。如果您仍然想使用弱属性,使用的正确模式是创建一个本地(强)引用,将其添加到超级视图,然后 然后 分配给属性 - 此时按钮将有一个拥有引用(超级视图),因此不会被 ARC 删除:

UIButton *button = [UIButton buttonWithType:whatever];
[self.view addSubview:button];
self.button = button;

【讨论】:

  • 感谢您的解释。这有助于我的理解。为简单起见,我将所有 UI 属性声明为强。
猜你喜欢
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 1970-01-01
相关资源
最近更新 更多