iOS 8 UITableView separator inset 0 not working
iOS 8.0 introduces the layoutMargins property on cells AND table views.
This property isn't available on iOS 7.0 so you need to make sure you check before assigning it!
The easy fix is to subclass your cell and override the layout margins property as suggested by @user3570727. However you will lose any system behavior like inheriting margins from the Safe Area so I do not recommend the below solution:
(ObjectiveC)
-(UIEdgeInsets)layoutMargins {
return UIEdgeInsetsZero // override any margins inc. safe area
}
(swift 4.2):
override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }
If you don't want to override the property, or need to set it conditionally, keep reading.
In addition to the layoutMargins
property, Apple has added a property to your cell that will prevent it from inheriting your Table View's margin settings. When this property is set, your cells are allowed to configure their own margins independently of the table view. Think of it as an override.
This property is called preservesSuperviewLayoutMargins
, and setting it to NO
will allow the cell's layoutMargin
setting to override whatever layoutMargin
is set on your TableView. It both saves time (you don't have to modify the Table View's settings), and is more concise. Please refer to Mike Abdullah's answer for a detailed explanation.
NOTE: what follows is a clean implementation for a cell-level margin setting, as expressed in Mike Abdullah's answer. Setting your cell's preservesSuperviewLayoutMargins=NO
will ensure that your Table View does not override the cell settings. If you actually want your entire table view to have consistent margins, please adjust your code accordingly.
Setup your cell margins:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Remove seperator inset
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
// Prevent the cell from inheriting the Table View's margin settings
if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
[cell setPreservesSuperviewLayoutMargins:NO];
}
// Explictly set your cell's layout margins
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
Swift 4:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// Remove seperator inset
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
cell.separatorInset = .zero
}
// Prevent the cell from inheriting the Table View's margin settings
if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
cell.preservesSuperviewLayoutMargins = false
}
// Explictly set your cell's layout margins
if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
cell.layoutMargins = .zero
}
}
Setting the preservesSuperviewLayoutMargins
property on your cell to NO should prevent your table view from overriding your cell margins. In some cases, it seems to not function properly.
If all fails, you may brute-force your Table View margins:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Force your tableview margins (this may be a bad idea)
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
}
Swift 4:
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Force your tableview margins (this may be a bad idea)
if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
tableView.separatorInset = .zero
}
if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
tableView.layoutMargins = .zero
}
}
...and there you go! This should work on iOS 7 and 8.
EDIT: Mohamed Saleh brought to my attention a possible change in iOS 9. You may need to set the Table View's cellLayoutMarginsFollowReadableWidth
to NO
if you want to customize insets or margins. Your mileage may vary, this is not documented very well.
This property only exists in iOS 9 so be sure to check before setting.
if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
myTableView.cellLayoutMarginsFollowReadableWidth = NO;
}
Swift 4:
if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
myTableView.cellLayoutMarginsFollowReadableWidth = false
}
(above code from iOS 8 UITableView separator inset 0 not working)
EDIT: Here's a pure Interface Builder approach:
NOTE: iOS 11 changes & simplifies much of this behavior, an update will be forthcoming...
iOS 8 UITableView separator inset 0 not working
iOS 8.0 introduces the layoutMargins property on cells AND table views.
This property isn't available on iOS 7.0 so you need to make sure you check before assigning it!
The easy fix is to subclass your cell and override the layout margins property as suggested by @user3570727. However you will lose any system behavior like inheriting margins from the Safe Area so I do not recommend the below solution:
(ObjectiveC)
-(UIEdgeInsets)layoutMargins {
return UIEdgeInsetsZero // override any margins inc. safe area
}
(swift 4.2):
override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }
If you don't want to override the property, or need to set it conditionally, keep reading.
In addition to the layoutMargins
property, Apple has added a property to your cell that will prevent it from inheriting your Table View's margin settings. When this property is set, your cells are allowed to configure their own margins independently of the table view. Think of it as an override.
This property is called preservesSuperviewLayoutMargins
, and setting it to NO
will allow the cell's layoutMargin
setting to override whatever layoutMargin
is set on your TableView. It both saves time (you don't have to modify the Table View's settings), and is more concise. Please refer to Mike Abdullah's answer for a detailed explanation.
NOTE: what follows is a clean implementation for a cell-level margin setting, as expressed in Mike Abdullah's answer. Setting your cell's preservesSuperviewLayoutMargins=NO
will ensure that your Table View does not override the cell settings. If you actually want your entire table view to have consistent margins, please adjust your code accordingly.
Setup your cell margins:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Remove seperator inset
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
// Prevent the cell from inheriting the Table View's margin settings
if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
[cell setPreservesSuperviewLayoutMargins:NO];
}
// Explictly set your cell's layout margins
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
Swift 4:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// Remove seperator inset
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
cell.separatorInset = .zero
}
// Prevent the cell from inheriting the Table View's margin settings
if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
cell.preservesSuperviewLayoutMargins = false
}
// Explictly set your cell's layout margins
if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
cell.layoutMargins = .zero
}
}
Setting the preservesSuperviewLayoutMargins
property on your cell to NO should prevent your table view from overriding your cell margins. In some cases, it seems to not function properly.
If all fails, you may brute-force your Table View margins:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Force your tableview margins (this may be a bad idea)
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
}
Swift 4:
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Force your tableview margins (this may be a bad idea)
if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
tableView.separatorInset = .zero
}
if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
tableView.layoutMargins = .zero
}
}
...and there you go! This should work on iOS 7 and 8.
EDIT: Mohamed Saleh brought to my attention a possible change in iOS 9. You may need to set the Table View's cellLayoutMarginsFollowReadableWidth
to NO
if you want to customize insets or margins. Your mileage may vary, this is not documented very well.
This property only exists in iOS 9 so be sure to check before setting.
if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
myTableView.cellLayoutMarginsFollowReadableWidth = NO;
}
Swift 4:
if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
myTableView.cellLayoutMarginsFollowReadableWidth = false
}
(above code from iOS 8 UITableView separator inset 0 not working)
EDIT: Here's a pure Interface Builder approach:
NOTE: iOS 11 changes & simplifies much of this behavior, an update will be forthcoming...
How do I make the UITableView separator inset go from the edges of the screen?
Since launch of iOS 8.0, apple added layoutMargins property for UITableViewCell and UITableView.
So you can set layoutMargin to zero in willDisplayCell:
delegate method of TableView. This code just set tableview layoutMargin
and cell layoutMargin
as UIEdgeInsetsZero
.
This will work for iOS 7.0 also.
Try this may help you.
Swift
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if(tableView.respondsToSelector("setSeparatorInset:")){
tableView.separatorInset = UIEdgeInsetsZero
}
if(tableView.respondsToSelector("setLayoutMargins:")){
tableView.layoutMargins = UIEdgeInsetsZero
}
if(cell.respondsToSelector("setLayoutMargins:")){
cell.layoutMargins = UIEdgeInsetsZero
}
}
Objective C
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[tableView setLayoutMargins:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
For iOS 9.0, you have to set cellLayoutMarginsFollowReadableWidth
to NO
.
Objective C
- (void)viewDidLoad {
[super viewDidLoad];
//For iOS 9 and Above
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 9.0) {
self.tableView.cellLayoutMarginsFollowReadableWidth = NO;
}
}
Swift
override func viewDidLoad() {
super.viewDidLoad()
//For iOS 9 and Above
if #available(iOS 9, *) {
tableView.cellLayoutMarginsFollowReadableWidth = false
}
}
You can also set this value from Storyboard.
Open Storyboard and go to Attribute Inspector for TableView Cell.
Change type of Separator
field to Custom Insets
and change value of Left
to 0
.
Please find below image.
iOS 9 UITableView separators insets (significant left margin)
Okay, I have found out the solution. The only thing required for that is to set on the presenting instance of UITableView
that flag cellLayoutMarginsFollowReadableWidth
myTableView.cellLayoutMarginsFollowReadableWidth = NO;
I wanted to find some reference in the documentation but it looks like it is not ready yet, only mentioned on diff page.
As the flag was introduced in iOS 9 for the backward compatibility you should add a check before trying to set it:
if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
myTableView.cellLayoutMarginsFollowReadableWidth = NO;
}
For Swift 2.0
you can use #available
to check iOS version.
if #available(iOS 9, *) {
myTableView.cellLayoutMarginsFollowReadableWidth = false
}
Moreover you need to compile it with Xcode 7
or above.
EDIT
Please keep in mind that this is the only required fix if your separators looked "fine" up to iOS 8, otherwise you need to change a bit more. You can find info how to do this already on SO.
Remove SeparatorInset on iOS 8 UITableView for Xcode 6 iPhone Simulator
Thanks Student for pointing me to the right direction with the comment "Try this self.myTableView.layoutMargins = UIEdgeInsetsZero;" This line of code will only work on iOS 8 because layoutMargins is only available from iOS 8. If I run the same code on iOS 7, it will crash.
@property(nonatomic) UIEdgeInsets layoutMargins
Description The default spacing to use when laying out content in the view.
Availability iOS (8.0 and later)
Declared In UIView.h
Reference UIView Class Reference
Below is the right answer to solve this weird white space by setting the tableview layoutMargins
and cell layoutMargins
as UIEdgeInsetsZero
if it exists (for iOS 8). And it will not crash on iOS 7 as well.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[tableView setLayoutMargins:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
See the screen shot below:-
Separator insets not working
You have to subclass UITableViewCell and call layoutSubviews from your newly created UITableViewCell class, in the layoutSubviews method, use
- (void)layoutSubviews{
[super layoutSubviews];
self.imageView.frame = CGRectMake(0, 0, 50, 50); // override frame of your choice
}
Related Topics
Remove Alpha Channel in an Image
Presenting Modal in iOS 13 Fullscreen
Send Array of Request Body in an Alamofire Request
Swift Tableview in a Uiview Not Displaying Data
How to Change Status Bar Text Color in Ios
How to Change Button Title Alignment in Swift
How to Check How Long Ago Was the App Last Opened
How to Get Height of Uitableview When Cells Are Dynamically Sized
Iphone 6 and 6 Plus Media Queries
How to Do Base64 Encoding on Ios
Swift - Json Error: the Data Couldn'T Be Read Because It Isn'T in the Correct Format
Take Screenshots in the iOS Simulator
Post Request Using Application/X-Www-Form-Urlencoded
Swift Parse Json - the Data Couldn'T Be Read Because It Isn'T in the Correct Format