iOS 9 View Not appearing - ios

I have noticed a that a uibutton is not showing in my app when run in iOS 9 (works fine in earlier OS versions). I know several have noticed a similar issue with storyboards (https://forums.developer.apple.com/thread/14003), though I am not using those and am instead building my view programmatically. There is no autolayout or autoresizingmask to worry about.
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(SUG_MARGIN, self.mainView.bounds.size.height - 40 - margin, self.mainView.bounds.size.width-margin*2, 40);
[button setTitle:NSLocalizedString(#"...", nil) forState:UIControlStateNormal];
button.titleLabel.font = //...;
button.backgroundColor = //...;
[self.mainView addSubview:button];
NSLog(#"main:%#\nadd:%#\nsuper:%#", NSStringFromCGRect(self.mainView.frame), NSStringFromCGRect(button.frame), button.superview);
That nslog shows everything set up correctly.
I have similar buttons all over the app, but this is the only one that is not appearing, which is why I am scratching my head.

Refactored code to assign only measure frames in viewWillLayoutSubviews and it now works. strange.

Related

Still no solution for my uibutton position [duplicate]

I am under one project.In that I created one uibutton at bottom of my viewcontroller using code (Not via storyboard).But when i run my app,my uibutton are placing in differents positions.for example in iphone 5,6 simulator are in some position.In 4s,ipad simulator my uibutton is unvisible.Also i check with my own device(iphone 6) ,in that also my uibutton is not able to see.
Needed
I used below code for creating & placing my button position.but its not fit in one position.
CGFloat buttonSize = 40;
UIButton * disButton = [[UIButton alloc] init];
disButton.backgroundColor = [UIColor redColor];
UIImage *btnImage = [UIImage imageNamed:#"23"];
[disButton setImage:btnImage forState:UIControlStateNormal];
disButton.frame = CGRectMake(150, 523, 40, 40);
[overlayView addSubview:disButton];
[disButton addTarget:self action:#selector(dismissPopUpViewController)
forControlEvents:UIControlEventTouchUpInside];
In my code i use to place position in this line:
disButton.frame = CGRectMake(150, 523, 40, 40);
=> x-position = 150
=> Y-position = 523
Kindly please give some code solution for this problem.
As per all comments about your question.You need to set constraint for your UIButon.Use only centre x,centre y because that will helpfull to see your layout in all devices. And there is a already solution for your problem.see these below links for setting auto layout for UIButton
Link 1
Link 2
Link 3
Sure this will help you !

which is give best performance storyboard or .Xib file?

i am doing one simple apps project and using storyboards. but i am confuse to use either storyboard or xib file in my project ?
which of the best as performance base.
There is no performance improvements in Storyboard versus Xib files, they both are modified XML files. However storyboards are meant to be easier to use and give better overall look of your app. My personal experience is that storyboards are OK for really small apps(let's say 3-4 screens at top), however if you have complex app with 10-15 screen storyboards becomes a nightmare to maintain.
UPDATE
Also what I don't like about storyboards, is that if I wan't to reuse some screen in other application, I'll have to copy .m and .h files, and then search through storyboard to find my related interface file and put it inside new storyboard. Without them I'll just copy paste h,m,xib files(which I usually put in separate folder) for each screen at new project and use them.
Solution for you last comment :
you can use following code for designing UIButton dynamically-
int yPosition = 0;
for (int i = 0; i<10; i++){
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setBackgroundColor:[UIColor blackColor]];
[aButton setTitle:[NSString stringWithFormat:#"Button %d",index] forState:UIControlStateNormal];
[aButton setFrame:CGRectMake(20, yPosition, 100, 50)];
[aButton addTarget:self action:#selector(aButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aView addSubview:aButton];
yPosition += 50;
}
- (IBAction)aButtonClicked:(id)sender
{
NSLog(#"Clicked on button with title %#",[sender titleLabel].text);
}

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.
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."
#TotumusMaximus You have misunderstood what the documentation is saying. Note the first part:
If you subclass UIButton...
What this means is that if you try to do [MyAwesomeButton buttonWithType:UIButtonTypeCustom], the object that will be created will be a UIButton instance, NOT a MyAwesomeButton instance. In order to get a MyAwesomeButton instance, then you would need to do [[MyAwesomeButton alloc] init]. There are no button subclasses involved in the OP's problem, so this portion of the documentation does not apply here.
If your properties are weak, and you directly assign a newly created object to them, then by the rules of ARC they should immediately be deallocated and set to nil, since nothing else holds a strong reference to them. The fact that is was working on other devices / simulators was an accident of implementation.
There is no real need to use weak properties for UI elements now that views are not unloaded under memory pressure conditions any more. If you do still want to use weak properties, the correct pattern to use is to create a local (strong) reference, add it to a superview, and then assign to the property - at this point the button will have an owning reference (the superview) so will not be removed by ARC:
UIButton *button = [UIButton buttonWithType:whatever];
[self.view addSubview:button];
self.button = button;

Button not showing on phone but yes on XCode simulator

I've created a popup UIView that is a subview of my main view and a UIButton that is a close button that is a subview of my main view.
As shown in the picture the button shows in the XCode iPhone simulator in my Mac but when I test it in the physical phone the ICON/Button is not showing.
Why is not showing on my actuall phone but yes on the simulator? I've no errors, not even in the Phone console.... I have no idea how to debug this.
- (void) addCloseButton:(UIView*)myView {
CGRect position = CGRectMake(myView.frame.origin.x - 20, myView.frame.origin.y -20, 40, 40);
UIButton* myCloseButton = [[UIButton alloc]initWithFrame:position];
[myCloseButton setBackgroundImage:[UIImage imageNamed:#"close"] forState:UIControlStateNormal];
myCloseButton.tag = 45;
[myCloseButton addTarget:self action:#selector(removePopup)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myCloseButton];
}
Try tapping where the button should be. If that works as intended, it is probably just a problem loading the asset.
The simulator is case-insensitive, devices are not.

UIButton doesn't listen to content mode setting?

firstButton is a UIButton of type Custom. I'm programmatically putting three of them across each cell of a table, thusly:
[firstButton setImage:markImage forState:UIControlStateNormal];
[firstButton setContentMode:UIViewContentModeScaleAspectFit];
[cell.contentView addSubview:firstButton];
Elsewhere, I'm telling it to clipToBounds. What I get is a crop of the center square of the image, rather than an aspect-scaled rendering of it. I've tried this lots of ways, including setting the mode property on firstButton.imageView, which also doesn't seem to work.
I had the same problem. I see this question is a little old, but I want to provide a clear and correct answer to save other folks (like me) some time when it pops up in their search results.
It took me a bit of searching and experimenting, but I found the solution. Simply set the ContentMode of the "hidden" ImageView that is inside the UIButton.
[[firstButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[firstButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
Perhaps that's what Dan Ray was alluding to in his accepted answer, but I suspect not.
If you're dealing with the UIButton's image (as opposed to it's backgroundImage), setting the contentMode on the UIButton itself or on its imageView has no effect (despite what other answers say).
Alternatively do this instead:
self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
Or size your image accordingly.
OR just use a UIImageView (which properly respects contentMode) with a UITapGestureRecognizer attached to it, or a transparent UIButton on top of it.
Rather than setting the contentMode on the button itself, you'll want to set contentHorizontalAlignment and contentVerticalAlignment properties and (crucially) the contentMode for the button's imageView for any kind of aspect fill or fit:
button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageView?.contentMode = .scaleAspectFit
You can also do other things like aligning the button's image to the top. If you don't need an aspect fill or fit, you just can set the alignment by itself:
button.contentVerticalAlignment = .top
After a couple of hours of confusion, here's how I got it to work under iOS 3.2. As dusker mentioned, using setBackgroundImage instead of setImage did the job for me.
CGRect myButtonFrame = CGRectMake(0, 0, 250, 250);
UIImage *myButtonImage = [UIImage imageNamed:#"buttonImage"];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setBackgroundImage:myButtonImage forState:UIControlStateNormal];
[myButton setFrame: myButtonFrame];
[myButton setContentMode: UIViewContentModeScaleAspectFit];
The answer is to use a UIImageView with all the lovely Content Mode settings you want, and then layer a custom button on top of it. Dumb that you can't do that all in one shot, but it appears that you can't.
These two things (which are quite hard to find initially) will stretch your UIButton image to fit the button size:
one should always try to set such in the Storyboard rather than code.
Found a fix for this. Set the adjustsImageWhenHighlighted property of UIButton to NO.
UIButton *b = [[UIButton alloc] initWithFrame:rect];
[b setImage:image forState:UIControlStateNormal];
[b.imageView setContentMode:UIViewContentModeScaleAspectFill];
[b setAdjustsImageWhenHighlighted:NO];
Hope this helps. Feel free to comment below, I will follow up on any questions that you have.
My answer is similar to Kuba's. I needed my image to be programatically set.
UIImage *image = [[UIImage alloc] initWithContentsOfFile:...];
[button setBackgroundImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill; //this is needed for some reason, won't work without it.
for(UIView *view in button.subviews) {
view.contentMode = UIViewContentModeScaleAspectFill;
}
Only solution which worked for me:
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
Swift 3
self.firstButton.imageView?.contentMode = .scaleAspectFill
For anyone experiencing this on iOS 15 and Xcode 13, see Matt's answer in this other question.
The behavior of Xcode changed and now defaults UIButtons from the library to the plain style, which prevents the child image from scaling as expected.
Instead of setImage try setBackgroundImage
I believe we have a simple interface builder issue here - apparently the IB ignores any content-mode changes AFTER you have set the image-property.
the solution is as simple: set the content mode, remove previously set image-names (make sure you remove it in all states, default, highlighted etc.), then re-enter the desired image-names in all desired states - et voilĂ .
I also advice to have a look at the adjustsImageWhenHighlighted UIButton property to avoid weird deformations of the image, when the button is pressed.
In trying to figure this out, my method got a bit hackier as time went on, and I wound up subclassing UIButton and overriding setHighlighted:
For me it works to just knock down the image alpha to .5, because they're on a black background.
However, it only works if I comment out [super setHighlighted:] (where it appears the image-stretchy code is going on), which just doesn't feel like the right way to solve this at all...everything seems to be working fine, though. We'll see how it holds up as I keep working on it.
- (void)setHighlighted:(BOOL)highlight {
if (highlight) {
[self.imageView setAlpha:.5];
} else {
[self.imageView setAlpha:1];
}
// [super setHighlighted:highlight];
}
If anyone looking for answer that work in iOS 6 and iOS 7 and storyboard:
You can set image in your storyboard:
And then:
for(UIView* testId in self.subviews) {
if([testId isKindOfClass:[UIImageView class]])
[testId setContentMode:UIViewContentModeScaleAspectFill];
}
If the UIButton does not seem to listen to the layout constraint settings, do check whether the images are larger than the button size. Always use the #2x and #3x images for retina resolutions.

Resources