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

I have the code below to add some UIBarButton to my project. This works great on the following:

Everything on iOS 7.1

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

I do not have an iPhone 5 device for testing.

It does not work on the new iPhone 5s. What else?

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 went through the code and all the properties are not zero and have valid values. I also checked that all images are the right side.

How will this work on every device on the simulator, and not on the iPhone 5S?

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

Buttons are not displayed at all. Compiler warning and no console errors.

UPDATE

Tested the above code on iPhone 5 and it works great. This leads to the fact that it should be connected with the 64-bit iPhone 5S?

UPDATE 2

I removed all the code from the method and changed it to a very simple button:

  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; 

Now it does not work on any devices or simulators.

What am I doing wrong here?

Update 3 - Solution!

That's right, it was one simple thing that caused all this fuss. I announced that my UIButtons are weak , not strong - did I get the impression that the user interface elements should be weak, as they often go out of view?

I came up with this answer using the comments section.

This also does not explain why it works on the iPhone 4S and iPhone 5, declared weak . He also worked on a 64-bit simulator declared as weak

Does this mean that the 64-bit simulator should be used as a guide, and the actual testing should be performed on the device, since it seems that the simulator is not accurate when it comes to testing UIKit ?

I would like to know more about this.

+7
ios objective-c iphone
source share
3 answers

The problem was that [UIButton buttonWithType:UIButtonTypeCustom] does not leave an instance of the object, as indicated in Apple Docs. And UIBarButton is expecting some kind of instance. https://developer.apple.com/library/ios/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html

The solution, as stated in AppleDocs, uses the alloc + init construct to create the 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 instantiate a specific subclass, you must specify / run the button directly."

+6
source share

@TotumusMaximus You misunderstood what the documentation says. Pay attention to the first part:

If you are a subclass of UIButton ...

This means that if you try to execute [MyAwesomeButton buttonWithType:UIButtonTypeCustom] , the object to be created will be an instance of UIButton, not an instance of MyAwesomeButton. To get an instance of MyAwesomeButton, you need to do [[MyAwesomeButton alloc] init] . There are no button subclasses in the OP problem, so this part of the documentation does not apply here.

+2
source share

If your properties are weak, and you directly assign a newly created object to them, then according to ARC rules they should be immediately released and set to zero, since nothing else contains a reference to them. The fact that it worked on other devices / simulators was a case of implementation.

There is no real need to use the weak properties of the UI elements, since now the views are not unloaded under conditions of excessive pressure. If you still want to use weak properties, the correct template to use is to create a local (strong) link, add it to the supervisor, and then assign the property - at that moment the button will have a link to the owner (superview), so ARC will not be deleted:

 UIButton *button = [UIButton buttonWithType:whatever]; [self.view addSubview:button]; self.button = button; 
+2
source share

All Articles