There is a problem when you try changing UINavigationItem (in my case it is setting searchViewController) after the view was loaded: UINavigationBar does not change it's size to fit the new content. Strangely this bug is only noticed in iOS 13, everything was fine on older versions.
I have made a minimum reproducible example here https://gist.github.com/sam-moshenko/2e0310fe6e6dddace5f464e13ae3f972
The solution is also visible in the example https://gist.github.com/sam-moshenko/2e0310fe6e6dddace5f464e13ae3f972
But it is commented out in line 8.
Solution is to manually update the UINavigationBar's size by calling sizeToFit.
I have a project that was built last year, and it uses XIBs, no storyboards. The XIBs do not use Auto Layout, but they do use some Autosizing. I have an issue when running with iOS7, in which all the views are tucked under the status bar. I fully understand this is a new feature with iOS7, in which this can be expected. However, all of the solutions for fixing it to not do this are not working. I have an image at the top of the view that always shows under the status-bar, and I'm not using nav-bars or anything like that.
I have tried updating the Y-deltas in the XIB (they have no effect on the view), I have tried setting the edgesForExtendedLayout to UIRectEdgeNone (does nothing), and a multitude of other things. Every time, the status bar shows with the view tucked under it, no matter what I do.. that is unless I manually move down the view in the XIB to allow room for the status bar (but that solution doesn't work because it doesn't look right in iOS6, of course).
What's odd is that even when I try a line of code to hack in a view-shift, it doesn't work (like the following):
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+20, self.view.frame.size.width, self.view.frame.size.height);
..Not that I would go with that kind of solution, but it's just odd that it didn't work (the only time I typically see that not work is if Auto Layout is in place, which it's not in this case).
It is a design requirement that the status-bar shows, and I'm just stumped on why I can't set the view to be under the status bar for iOS7. I have read every single Stack Overflow post on the subject, as well as Apple's transition/guides. Once again, to reiterate, I fully understand how it should function and what the expected solution should be to this, but none of that seems to be working for this particular project.
I am an experienced iOS dev, but this project was built by another team, so I don't know if there's something hidden somewhere in the XIB files, plist, or code that could be trumping the above settings. Please let me know if there is something else that can be looked at on this, or more information I can provide.
Thanks in advance!
If you set the iOS 6/7 delta values in Interface Builder, remember to set "View as" to "iOS 6" on the Interface Builder Document, since it is the iOS 6 layout you want to replicate. The deltas will then be used only on iOS 7 to push the content below the status bar. If you leave "View as" set to iOS 7 (the default) the deltas will instead give you the iOS 7 look on iOS 6.
However, the deltas will not help you if you reposition or resize views programmatically based on the view frame, since the frame does not account for the deltas.
Instead of using the deltas, the best solution I have found is to enable Auto Layout on your main XIB and then set the top space constraint on your top/content view to follow the Top Layout Guide. This guide was introduced in iOS 7 and represents the position below the status bar. Unfortunately the guide is not available in Interface Builder when not using Storyboards, but you can add it programmatically.
What I did was add a top space constraint to the superview instead in Interface Builder, and created an outlet for this in the code. Then, in viewDidLoad, if the topLayoutGuide is available (iOS 7+), replace the constraint in this outlet with a version using the Top Layout Guide instead.
if ([self respondsToSelector:#selector(topLayoutGuide)]) {
[self.view removeConstraint:self.containerTopSpaceConstraint];
self.containerTopSpaceConstraint =
[NSLayoutConstraint constraintWithItem:self.contentView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.topLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0];
[self.view addConstraint:self.containerTopSpaceConstraint];
[self.view setNeedsUpdateConstraints];
[self.view layoutIfNeeded];
}
For reference, the solution below did work when I applied it to my ViewControllers. However, it's not ideal and a bit hacky. If it's the only approach I can take, then so be it, though.
float systemVersion=[[[UIDevice currentDevice] systemVersion] floatValue];
if(systemVersion>=7.0f)
{
CGRect tempRect;
for(UIView *sub in [[self view] subviews])
{
tempRect = [sub frame];
tempRect.origin.y += 20.0f; //Height of status bar
[sub setFrame:tempRect];
}
}
Apple are pushing you to use autolayout to accomplish this. You need to set a constraint to the "Top Layout Guide" from the top subview in your view.
See this document for examples:
https://developer.apple.com/library/ios/qa/qa1797/_index.html
To do this without XIBs, you'll need to add the constraint programatically. Apple's docs give a good example of this, which I've summarised below.
Giving that the topLayoutGuide is a property on a view controller, you just use it in your dictionary of variable bindings. Then you set up your constraint like normal:
id topGuide = [myViewController topLayoutGuide];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(button, topGuide);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[topGuide]-20-[button]" options:0 metrics:nil views:viewsDictionary];
The documentation for this can be found in the UIViewController class reference.
1)The simplest solution if you don't mind having an opaque navigation bar:
self.navigationController.navigationBar.translucent = NO;
2) svguerin3's answer can't work in the general case. For example, if one of your subviews uses autosizing to be hooked at the bottom of its container, then its new position will be wrong. And it could go out of screen in the worst case.
- (void)viewDidAppear:(BOOL)animated {
[self.view setFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height)];
// OR
self.view.transform = CGAffineTransformMakeTranslation(0, 20);
}
Have you tried viewing your XIBs as source and removing any line containing edgesforextendedlayout ??
We had to remove this line in our storyboard's scenes since our storyboard's scenes' main views are represented by XIBs
What was happening for us was that somehow, in some scenes, the XIB content for the scene's main view was being pushed down by the height of the status bar and the navigation bar.
Removing that line allowed the XIBs to be displayed as if their top originated at the same top of its storyboard's scene.
Sadly, we have no idea what triggered this, but I saw it happen when changing the order of the contents within the XIB's main view so that a UITextView appeared first. Rearranging the order of items after this was triggered had no effect in removing this unwanted behaviour.
Hope this helps anyone else running into this type of problem.
If you are using the storyboard, after setting the top layout of your view, you can uncheck the "Under Opaque Bars" in the Attributes Inspector
Basically, the title says everything. I'm trying to do some customization and i need to use less-than-zero width to make buttons be closer to each other.
I've learned it from this answer.
I can do it by manually setting every fixed space width, but how can I do it via [appearance] or something to make it default?
Something like this:
// works for every button not only Fixed Space
[UIBarButtonItem appearance] setWidth:-10];
!!! OR !!!
How can i set less-than-zero width in XCode? I'm creating everything using Storyboard anyway, it says that's not a valid value to set.
Any help would be really great.
I normally solve this kind of problem by subclassing the container and overriding layoutSubviews or didLayoutSubviews. This gives you a lot of control of all kind of styling behavior. In this particular case you would determine the widths programmatically and adjust the frames accordingly.
Make your instance class a subclass of this subclass, and you will have the layout code neatly separated from your implementation.
I have noticed a change in the look of the tableview cells in iOS 5, and I googles around a bit to see if anyone else had noticed. This fellow did, and posted this image. I can't reproduce it on every uitableview (if I could I would know where it came from and I could get rid of it), but it is certainly causing me a problem on one of my tableviews. Has anyone else noticed this - better yet, has anyone else found a way to get rid of it?
I had this issue, on an iOS4 phone or simulator it looks fine but for iOS5 it was a problem. I discovered that the issue was with the separator style for the table view. It looks like the default value is set to etched for iOS5. I have gone through my code and added the following line to my init method for all grouped table view controllers:
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
Which has fixed the issue for me, although I also set the following as the color appeared to be white not grey as in the previous version:
self.tableView.separatorColor = [UIColor lightGrayColor];
It was a problem for me as I have changed the background on all of my table views and the extra line didn't look good for my app.
use:
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
I want to remove the built in separation between cells in UITableView.
I tried using :
[self.myTableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
But that only removes the separator line.
I need the view to appear as if it's not a table view at all. (like the tableview is one big view who doesn't contain many separated cells)
Is that possible ?
Edit:
See the separation between the cells? I wan't it to disappear and the table view to be as if it's one big cell.
Edit 2:
The problem doesn't appear when I don't use an image view as the cell background, but just use a simple background color.
I tried using a different image, and as you can see the problem is much less obvious.
I would still appreciate a solution for the red image though, since I do have a lot of images that still can't be put as background currently. (Not sure why one image would cause the problem and other won't ,I guess something with the pic setting)
You can do something like
self.tableView.separatorColor = [UIColor whiteColor];
or
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
I suppose in your case it would be
self.myTableView.separatorColor = [UIColor whiteColor];
In the future you might want to search Stack Overflow as there are many similar questions.
Your separation is due to the background gradient in the red example and it is not coming from the tableView. in your second image there is no gradient so you don't see separation.
remove the gradient from the background image and it will be fine.
try to do this:
self.tableView.backgroundColor=[UIColor clearColor];
self.tableview.separatorColor=[UIColor clearColor];
self.view.backgroundColor=[UIColor yourcolor];
i don't remember if it's then color with image or backgroundwithimage or background with view.. don't remember, however logic way is this.
hope it's usefull
If you just want to get rid of the separator between UITableView cells. Two things you need.
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
Make sure your imageView ( in your tableview cell) has same height as tableview cell. This means your image view is fully covering the table view cell. Goto inspector view and verify the height , if you see the height is 43 just set it to 44 ( 44 is default tableview cell height for retina display).
Go StroyBaord -> Select Table -> Attribute inspector -> Separator None
No Separator Will Appear
You seem to have answered your own question. If you want a solid colored background, make an image with just a solid color. I suspect it's not best practice, but it will get the job done.
I've done this many times in my own applications. I understand that you wish to make your tableview look as if its not a tableview but as if its on a blank piece of paper.
Just a note for you, the reason you can see the separation with some images and not so much with others is due to its image texture. When you place copies of the image side by side, they dont have a continuous pattern thus forming obvious visual separations.
Solution:
Assuming you have the tableview setup in a xib file, display the background of the table itself to to clear -> then set the background of the view itself to whatever image you like. You will then have a tableview with the background view being transparent with only the main view behind it showing its image or color. Displaying your image on this canvas will mean a clear one image background.