Can not remove sub view from tableview custome cell - uitableview

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.

Related

Adding dynamic tags with title to UITableView header

I want to add dynamic tags with title into table view header when user select row(s).
Like if user selects 5 different cities from table view then I want to add those selected cities as different tags into table view header so that user can see selections with horizontal scrolling or anything else whichever suits best.
How can I achieve such functionality?
Any help would be much appreciable.
Thanks
This can be achieved by adding Collection View into the header of Table View.
Create an Array which will store selected row value.
Reload or Update the collection view with selected array data.
Have a UIScrollView just above the UITableView in StoryBoard.
When you get into - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method call following method,
- (void)addLabel:(NSString *)cityName {
[array addObject:cityName];
UILabel * label = [[UILabel alloc] init];
label.frame = CGRectMake(array.count*44, 0, 44, 44);
label.text = cityName;
[sview addSubview:label];
[sview setContentSize:CGSizeMake(array.count*44, 44)];
}
Here array is , object which holds the list of cities selected
UIScrollView is , a scroll view which is added above the UITableView in storyboard.
Every time when you call addLabel method by passing selected cityName, initialise a new UILabel with required properties and add that to UIScrollView. Here the 'x' origin of the UILabel is changing based on the number of elements added to array.
At the end set the contentSize to UIScrollView , so that scroll view scrolls till there.
If you need more customisation to showcase labels in scrollview, you can have a UIView with whatever the customisation you want, and then add the UILabel to UIView. At the end add this UIView to UIScrollView.

Section header view glitch in plain uitableview

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];

disclosure indicator moves cell subviews

I have a table with some cells using a disclosure indicator and some not.
Obviously the disclosure indicator scrunches the contents so not all of the cells line up together in perfect columns.
How can I adjust my contents to stay in the same location regardless of there being a disclosure indicator or not?
One trick to solve this issue is to create an empty view and use it as the cell's accessoryView. Do this only for the cells that don't have a detail disclosure.
The trick is setting the size of the view properly. A little trial and error should do it.
In your cellForRowAtIndexPath:... method:
UITableViewCell *cell = ... // get the cell
If (/* there is no detail disclosure */) {
// Try different "width" value for this view to get the desired results
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 40)];
cell.accessoryView = view;
}
Another alternative is to use different cells. One with the disclosure indicator, and one without. You then have complete control over the layout. And by using the cell reloading mechanism rather than the table reloading mechanism this is efficient.
Better than using blank views IMHO.

Prevent UITableViewCells from creating as you scroll down

I'm creating a mail screen using which visually resembles the iOS native email app. It looks like this (Both images are of the same screen. First one is the top half and the second one is the rest of it).
The difference is my mail screen has more custom fields in addition to normal To, Cc, Subjet fields.
I'm using a UITableViewController to create this. Below is a code snippet which creates a cell (For each cell it's pretty much the same).
- (UITableViewCell *)tokenTableView:(TITokenTableViewController *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
self.tableView.frame = CGRectMake(0,0,320,320);
UIView *contentSubview = nil;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifierSubject];
if(!self.txtSubject) {
self.txtSubject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.txtSubject.frame = CGRectMake(10, cell.frame.size.height / 2 - self.txtSubject.font.lineHeight / 2, tableView.tableView.bounds.size.width, 30);
self.txtSubject.placeholder = #"Subject";
[self setupMailData:indexPath.row];
}
contentSubview = self.txtSubject;
}
Say, I open up a draft. All the details in the input fields are filled and without changing anything, I hit send and it crashes the app. I know what's causing this. The problem is that normally the cells that are under the viewable portion of the screen gets created as you scroll down, right? But in this scenario, if I send it without scrolling down but those cells below the viewport don't exist thus it throws the error.
If I open the draft, scroll down and hit send, it works fine.
I need to know if there's a way to create all these cells at once. Even the cells that are below the viewport at first. Not depending on the user to scroll down.
I hope you have an idea about my situation. Can anyone suggest a solution?
Thank you.
follow steps:
Take uiscrollview and set scrollview frame as which you want to display.
Take uitableview as a subview of uiscrollview
set property Scrolling Enabled = NO (uncheck checkbox in .xib) of uitableview
call reloaddata method of uitableview
set tableview frame and contentsize of scrollview
tblEmail.frame = CGRectMake(yourXPos, yourYPos, yourWidth, tblEmail.contentSize.height);
scrollObj.contentSize = CGSizeMake(yourScrollWidth,tblEmail.contentSize.height+10);
so, the height of tableview is equal its contentsize. so, its create all cells at a time. and set contentsize of scrollview is equal tableview contentsize. so, the scrolling feature is worked like uitableview scrolling...
Use a Storyboard, add a UITableViewController and set the 'Content' to StaticCells.
Then you can define all the cells and their content in the Storyboard. You can even wire stuff up to IBOutlets in your UITableViewController subclass and they will all be there for you when viewDidLoad is fired ...
When using a Storyboard your code for getting the ViewController looks like:
[[UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil] instantiateInitialViewController];

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