Section header view glitch in plain uitableview - ios

I have a UITableView of type plain table view with two sections and a dynamic number of rows.
Also I am returning a UIView for the section header.
Everything works perfect except when the table reloads. The section header position moves to a random position until the view begins to scroll.
Autolayout within the header view and super view seem not violating.
I have set the table footer view either nil or show paginating animation.
And the table view is within a scroll view.
Any suggestion or solution why this glitch occurs for section header.
And this glitch only occurs in iOS 9

Problem for me was independently from refresh control, although it is part of my view controller.
It was related to estimatedRowHeight and rowHeight.
I found an empirical solution. My issue happened when going back and forth between view controller and the tableview reloaded.
Because my cells have variable height, I had:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0f;
so I can deal with cell autoresize.
Apparently the problem was with the estimatedRowHeight. When I changed the value with the maximum cell row height the glitch disappeared. The table section wasn't jumping anymore. I used the view inspector to calculate the row height based on my worst use case.
Note #1
I don't know how it performs with a thousand cells. estimatedRowHeight should be used to calculate the entire content offset so considering the worst case might be
inefficient.
Note #2
When calculate the maximum cell height keep in mind to consider the case when the font size can be increased by the system preference, if the cell is registered to these changes.

My issues get resolved as follows.
Initially I have added refresh controller as a subview of table view.
_chatListRefreshControl = [[UIRefreshControl alloc] init];
_chatListRefreshControl.transform = CGAffineTransformMakeScale(0.7, 0.7);
[_chatListRefreshControl addTarget:self
action:#selector(refreshChatListView:)
forControlEvents:UIControlEventValueChanged];
[self.myChatsTableView addSubview:_chatListRefreshControl];
I have modified that to as follows: Changed the refresh indicator from table view to table view controller's property.
UITableViewController *chatTableViewcontroller = [[UITableViewController alloc] init];
chatTableViewcontroller.tableView = self.myChatsTableView;
_chatListRefreshControl = [[UIRefreshControl alloc] init];
_chatListRefreshControl.transform = CGAffineTransformMakeScale(REFRESH_INDICATOR_SCALE_FACTOR, REFRESH_INDICATOR_SCALE_FACTOR);
[_chatListRefreshControl addTarget:self action:#selector(refreshChatListView:) forControlEvents:UIControlEventValueChanged];
chatTableViewcontroller.refreshControl = _chatListRefreshControl;
[self addChildViewController:chatTableViewcontroller];

Related

Can not remove sub view from tableview custome cell

When table will be scroll it will repeat subview on cell, I am use below code for display embedded view on tableview custome cell. any one know so please help me. How to resolve this issues.
long tag = 100 + indexPath.row;
URLEmbeddedView *embeddedView = [custom.contentView viewWithTag:tag];
if ([custom.contentView viewWithTag:tag]) {
[embeddedView loadURL:#"" completion:nil];
[embeddedView removeFromSuperview];
}
embeddedView = [[URLEmbeddedView alloc] initWithFrame:CGRectMake(35, 60, 220, 110)];
//URLEmbeddedView *embeddedView = [[URLEmbeddedView alloc] initWithFrame:CGRectMake(custom.img_bgOther.frame.origin.x + 35, custom.img_bgOther.frame.origin.y + 50, 220, 110)];
embeddedView.tag = tag;
[custom.contentView addSubview:embeddedView];
[embeddedView loadURL:str_Website completion:nil];
Presumably the code in your question is taken from your cellForRowAtIndexPath: method. The problem you describe is a consequence of cells being reused. Cells for rows that have scrolled off screen are reused for rows that scrolling on screen. Suppose row 0 is scrolled off screen. It will have an embedded view with tag 100. And suppose it is reused for row 10. The above code will try to find a view with tag 110 and remove it from its superview. Since the tag does not match, the existing embedded view is not removed, and the new embedded view is added on top of it.
I would suggest you do things differently. You shouldn't be adding and removing the embedded view in cellForRowAtIndexPath. You have a custom cell, so just design the embedded view into it. Create a URLEmbeddedView property in your custom cell class, so you can access that subview without having to use viewWithTag. You can use that property to call the loadURL:completion: method with the correct values for the current row.
When cells are reused, the tableView will call the cell's prepareForReuse method. So override that method in your custom cell class, and clear the loadURL/completion at that point.

UITableViewCells scroll over header when scrolling down

I'm trying to figure out what my options are for having the top of a UITableView be able to stay at rest about 1/3 down the screen but still be able to scroll over the top of an image above it.
I was thinking UITableView on a UIScrollView but I haven't seen this exact thing while googling around for it.
Basically I'm looking to have a header and then the table view will scroll over the top of the header without the header moving. If I set the table view below a simple uiview or imageview, it will always be below it.
Any suggestions?
Add your header as a separate view below your table view. Your table view should completely overlap the underlying view, as if it would obscure it. Then set the table view's tableHeaderView to a transparent UIView, through which you will be able to see your underlying header view. Your table view's background colour should also be clear.
CGRect headerFrame = self.underlyingHeaderView.bounds;
UIView *transparentView = [UIView alloc] initWithFrame:headerFrame];
transparentView.backgroundColor = [UIColor clearColor];
self.tableView.tableHeaderView = transparentView;

UITableView scrolls bounces back to top

I've been to a lot different questions on StackOverflow, But I just can't figure what is wrong here.
I have a view controller that receives data from a JSON, creating an array, and, then, it builds an UITableView, with fixed heights.
The issue is that I can't scroll to the bottom. It just bounces back.
- (UITableViewCell* )tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"SettingsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
[cell.detailTextLabel setNumberOfLines:2];
NSDictionary* place = [_placesData objectAtIndex:indexPath.row];
[cell.textLabel setText:[place valueForKey:#"nome"]];
[cell.detailTextLabel setText:[place valueForKey:#"endereco"]];
[cell.detailTextLabel setLineBreakMode:NSLineBreakByWordWrapping];
[cell.detailTextLabel sizeToFit];
UIImage* originalImage = [UIImage imageNamed:#"encontre.png"];
UIImage* resized = [UIImage imageWithCGImage:[originalImage CGImage]scale:(originalImage.scale * 1.8) orientation:(originalImage.imageOrientation)];
cell.imageView.image=resized;
cell.textLabel.font = [UIFont fontWithName:#"GillSans" size:17];
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.font = [UIFont fontWithName:#"GillSans-Light" size:17];
self.tableView.scrollEnabled=YES;
self.tableView.bounces=YES;
[self.tableView setAlwaysBounceVertical:YES];
return cell;
}
I have no idea on what else to do. Already tried to set the contentSize.height manually, force bounces and scrollEnabled on almost evert piece of code on the view controller.
Regards.
The way UITableView works is that it requires to know each row height in order to be able to compute its size.
The default behavior is to assume each row height is 44px. Which was clearly not your case here as you said it was 70px. That's why you had to change it in order to be able to scroll all way down
For instance let's say you had 10 rows. With default row height your table view was only able to scroll down to 10*44 = 440px thus the bouncing effect you got.
By setting the row height to 70px your tableview now goes down to 10*70 = 700px
can you check in the xib of your ViewController, select your tableView and click "size inspecto" in the right menu and you change in "iOS 6/7 Deltas":
you can tape -20 in height
i think the problem is in adaptation with ios7 and 6
I just had the same problem.
My solution was to update the contentSize before reloading the table's data.
tableViewOffre.contentSize = CGSizeMake(tableViewOffre.frame.size.width, [app.offres count] * 105);
Where 105 is my row height.
I think it isn't the best way to solve the problem (pretty dirty way I guess) but it's the only solution found.
Try implementing the UITableViewDelegate method tableView: heightForRowAtIndexPath:, don't let it get assigned automatically (i.e. sizeToFit). UITableView can be very unpredictable if you are not very specific and if you don't override certain methods.I had a unique problem with tableView scrolling back up to top automatically after I called [tableView reloadData]; This problem was unique because it only happened on iPad mini and iOS 8, every other device and OS was working properly. Hope it helps someone...
Actually your problem is related to frame of the table. by setting "Row height" is working for you because by chance count of row in your table and row height giving a table height that is suitable to you. But its not the right way of doing this.
Somewhere you need to check height of the table may be something like
Blockquote
(nameArray.count<10?kSACellHeight*nameArray.count:kSACellHeight*11))
Just managed to solve it, if anyone is having this same issue.
What I did is, inside the size inspector for my UiTableView, I manually set "Row Height" at 70 (the exact size I'm using).
After this, everything worked as a charm. But, if anyone can give a comprehensive explanation on what is really happening in here, it would be really great.
I've met with same issue.In my situation,I drag a tableview to a custom view controller,which is presented by a push segue.If the amount of data showed in tableview exceeds some number,then I can't touch the cell on bottom of the tableview.
Many ways have been tried:set the frame/content size of the table view,and none works for me.Finally,I find the root cause and solve it in a simple way(although not gracefully).
First,the root cause:the table view created by IB has a width larger then the its parent view controller.Thus,any cell out of view's bound will not be touched.
So,the solution is simple:Go to StoryBoard,adjust the width of table view,making it smaller than the width of parent view.It seems that if one table view is created by StoryBoard,you can't change its frame by code.That's what I've found up to now. I guess it's a bug of StoryBoard.
Help it be useful for other guys.
Keep in mind, my solution uses constraints. I ran across this issue while making a UITableView that can have a dynamic number of cells expand with more details. Here was my structure:
UIView
UIStackView
UIView (My Tabs Segue View)
UIView (My First Tab View)
UITableView (My Table I Wanted to be Scrolled)
UIView (My View if that Table was Empty)
UIView (My Second Tab View)
UITableView (My Second Table I Wanted to be Scrolled)
UIView (My View if that Table was Empty)
So, what I found out was that when I was setting the height constraint of the tables to the contentSize of the tables themselves. This originally helped account for the expandable part of the cell. But, if you want a table to be scrollable, you need to have its height shorter than its content height. By making it shorter (and having all the xib checkboxes checked as mentioned in other posts), it will automatically scroll. Granted, you can set its height via constraint or any way you want, just make sure its not the same as its content height!

UITableViewController and TableView Height

I am inheriting my view controller from UITableViewController. I have a header (logo), content (uitableview) and now I want to display the footer (uitabbar). But for some reason UITabBar is not visible. The space is being occupied by the UITableView. How can I fix this?
UPDATE 1:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
self.tableView.tableFooterView = self.tabBar;
}
I'm not sure you can put a UITabBar as a footer of a UITableView.
"footer of the tableView" meaning it won't be visible until you scroll your UITableView all way down past the last cell to then see the footer -- the header and footer of a tableView scrolls with the tableView content itself). Anyway in term of UX this seems very strange.
You probably want instead your UITabBar to always be visible at the bottom of your screen (and not being dependant of the scrolling of your UITableView). To do this, simply use a UITabBarController... that will then contain your UITableViewController (as the viewcontroller associated with one of its UITabBarItem)
[EDIT] See also Apple's View Controller Programming Guide and its paragraph about TabBarControllers.

Why is my UILabel in a UIView in a UITableCellView not updating after a correct database call, (it seems cell reuse related)?

I have a UITableview cell that gets a tally from a core data database. The tallyTable is in a view controller inside a UITab view. I have an NSLog statement that prints out the tally value whenever it gets updated. Another tab has a list to change the source (different day) for the tallies. I am using iOS5 with ARC targeting iOS 4.2.
Here's the problem. When I load the application, the correct tallies for whatever the last selected day show up in the table tab. If I then go to the day tab and change the day and return to the tally tab there is no change in the display. However, the viewWillAppear on the tally tab runs and as the table cycles through cellForIndexPath, my NSLog statement prints out all the correct new values. If I then scroll the top label off the screen and back the label updates to the new value.
I've tried setNeedsLayout and setNeedsDisplay on the UILabel, the UITableViewCell, the UITableView and the view controller loading the table. I tried changing the CellReuse identifier so that it would never reuse a cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CollectionItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CollectionItemTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.collectionKeys objectAtIndex:row] valueForKey:#"collectionTitle"];
NSInteger test1 = indexPath.row + 150;
NSLog(#"tag = %i", test1);
cell.tallyButton.tag = test1;
NSNumber * questionID = [[self.collectionKeys objectAtIndex:row] valueForKey:#"answerID"];
cell.tallyLabel.text = [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]];
NSLog(#"Collection text should be = %#", [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]]);
[cell setNeedsLayout];
return cell;
}
I've read over a half dozen other similar questions. Got about three hours invested so far in trying to solve this.
EDIT: I thought I fixed it by using the navigation controller to repush the top level view controller on to the view again. I'll admit now this feels like a classically kludgy hack in every way. When the view is PUSHED everything updates and it is seamless. However, in order to have a fixed footer to make selection settings for the table buttons, I used a UIView with two subviews, a UITableView on top and a simple UIView with four buttons below.
The captions on the buttons need to change with the data source. Now when the view controller is pushed onto the view it obscures my fixed footer view. So, I inserted the fixed footer into the UITableview and everything appeared fine until I scrolled the UITableView and the footer scrolled up with it. The table is basically a tally sheet with buttons next to each item and in the footer is four buttons to note the color of the tallied item. Say the next item was a green lego, you would tap "green" in the footer and the button next to "lego" in the table. When I push the view controller with the two subviews the UITableview labels do not update. Thus the tableview needs to be pushed itself (as far as I can tell).
ANSWER: see comment below but ultimately I needed to reload both the visible UITableView data and the delegate UITableView controller data behind it.
I'll give it a shot. First, are you using ARC? If not, you need to add autorelease when you alloc/init a new cell. Otherwise, it's fine as is.
If I'm understanding your question correctly:
The tableView displays the correct data at app launch
You switch away from the tab with the tableView and change the tableView dataSource
You switch back to the tab with the tableView and you see (via NSLog) that the table cells are reloaded with the correct data yet the old data is still visible in the cells
If you scroll a cell off the display and back forcing it to refresh it contains the correct data
Some thoughts:
the tableView will not reload itself automatically when it's view appears. You need to call [tableView reloadData] whenever the dataSource changes. This is independent of whether the tableView is currently displayed or not. My guess is this alone will solve your problem.
You don't need to call setNeedsLayout on the cell unless you want the cell to relayout its subviews based on the data. You also don't need setNeedsDisplay.
I'm assuming there aren't other complicating factors (such as multiple tableViews displaying the same data) that could confuse things.
If you use prepare for reuse method, remember to over the original method with [super prepareForReuse];
Another method if the above way does not work is re setup cell as describe here.
I use the same method i applied for some of my collection view : we should remove/reset your subview where you create/add it to cell 's content. That mean we need set up data each cell completely for each row.
I move the code reset data value from prepare reuse to where i set value and I worked simply !
In my CustomCell.m :
- (void)configCellWith:(id)item At:(NSUInteger)row {
if (_scrollView) {
[[_scrollView subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
_scrollView = nil;
[_scrollView removeFromSuperview];
}
else {
CGFloat y = labelHeight+15;
float scrollHeight = _imgArray.count*200;
_scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(10, y,SCREEN_WIDTH-20, scrollHeight)];
_scrollView.scrollEnabled=YES;
_scrollView.userInteractionEnabled=YES;
_scrollView.layer.masksToBounds = YES;
[self.contentView addSubview:_scrollView]; } }
Remember to change your data source appropriately too.

Resources