Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would this code work on iPhone 5, 4 and 4s but not 5s?

I have the below code for adding some UIBarButtons to my project. This works just fine on the following:

All on iOS 7.1

  • Simulator iPhone Retina 3.5 inch;
  • Simulator iPhone Retina 4 inch;
  • Simulator iPhone Retina 4 inch (64 bit)
  • Iphone 4
  • iPhone 4s

I don't have an iPhone 5 device to test though.

It doesn't work on a new iPhone 5s. Whats different?

Here is the code:

    -(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];
    }
}

I've stepped through the code and all the properties are not nil and have valid values. I've checked all images are the correct side, too.

How would this work on every device on simulator and not an actual iPhone 5S?

Also, since the two phones (iPhone 4S and 5S) have the exact same screen width and iOS version I am really puzzled?

The buttons don't show up at all. No compiler warning and no console errors.

UPDATE

Tested the above code on a iPhone 5 and it works just fine. This leads be to believe it must be something to do with the 64bit of the iPhone 5S?

UPDATE 2

Removed all the code from the method and changed it to a very simple button like this:

         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;

This now doesn't work on any devices or simulators.

What am I doing wrong here?

Update 3 - Solution!

Right, so it was one simple thing that caused all this fuss. I declared my UIButtons as weak and not strong - I was under the impression that UI elements needed to be weak as they go off view so often?

I came to this answer with the help from the comments section.

This also does not explain why it works on iPhone 4S and iPhone 5 when declared as weak. It also worked on the 64 bit simulator declared as weak

Does this mean the 64bit simulator is to be used as a guide and actual testing must be done on the device as it seems the simulator is not accurate when it comes to UIKit testing?

I'd love to know more about this.

like image 755
Robert J. Clegg Avatar asked Apr 01 '14 16:04

Robert J. Clegg


1 Answers

The problem was that [UIButton buttonWithType:UIButtonTypeCustom] doesn't leave an instance of the object as is stated in the Apple Docs. And the UIBarButton expects an instance of some sorts. https://developer.apple.com/library/ios/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html

The solution as is stated in the AppleDocs is using the alloc+init construction to make a button.

buttonWithType:

"This method is a convenience constructor for creating button objects with specific configurations. If you subclass UIButton, this method does not return an instance of your subclass. If you want to create an instance of a specific subclass, you must alloc/init the button directly."

like image 92
Totumus Maximus Avatar answered Sep 22 '22 12:09

Totumus Maximus