Prevent UITableViewCells from creating as you scroll down - ios

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

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.

UITableViewCell display under other view

I cannot convince UITableViewCell to display under another view as per the attached image. It happens when I embed UITableView into UIViewController.
VoucherTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"VoucherTableViewCell" forIndexPath:indexPath];
if (cell == nil) {
cell = [[VoucherTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"VoucherTableViewCell"];
}
Image one is before scrolling up.
Image two is the problem.
just try in viewDidLoad this code
self.edgesForExtendedLayout = UIRectEdgeNone;
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, yourTopiew.height, 0);
Follow these steps...
1. Make sure you are using correct Size class for iPhone.
2. Remove your tableView constraints if any.
3. Position your tableView correctly. (Bottom of your buttons)
4. Add top,bottom, left, right constraint to tableView.
5. Also make sure your buttons have correct constraints.
The problem is with the frame and positioning of your table view.
First the table view is places above the buttons in the view hierarchy in you nib file.
Second you need to set the frame and constraints of the tableview as such that it starts right from where the buttons end.

Horizontal and Vertical scrolling UITableViews

I am trying to implement a horizontal scrolling UITableView on the iPad, just like the Raombi app, in which the left panel sticks to its own place when scrolling horizontally. Moreover the UITableView is based on a columnar approach so it should scroll seamlessly together.
I have no idea how to start in order to fulfil these requirements.
Here is the screenshot of the desired functionality.
In viewDidLoad just rotate your table to 90 degree and load cells by rotating every cells to -90 degree. Consider your first column as table header and rest every column as table cell.
Go through below.Add this in viewDidLoad
self.tblDetail.transform = CGAffineTransformMakeRotation(-M_PI_2);
And below lines in cellForRowAtIndexPath method
if(!cell){
UIViewController *controller=[[UIViewController alloc] initWithNibName:CellIdentifier bundle:nil];
cell=(MyCustomCell *)controller.view;
cell.transform = CGAffineTransformMakeRotation(M_PI_2);
}
Apart from that design your header and cell in different nib files. For header just do as below:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
MyHeaderView *myView = //Your view instantiation code
myView.transform = CGAffineTransformMakeRotation(M_PI_2);
return myView;
}
I think this view is too complex to show in the one screen and generate it.
Since the iphone size is too less to display above view easily. Still if the following links useful to you please use it and get back to me.
I hope the following links are useful to you.
1)
http://code4app.net/ios/Multiple-Columns-TableView/4f901ef306f6e7123a000000
2)
http://code4app.net/ios/XCMultiSortTableView/520881e56803fa991f000000
3)
http://code4app.net/ios/RATreeView/524e2f896803fa6e31000001
4)
http://code4app.net/ios/Multiple-columns-Table/51e4dd116803fa1026000000
5)
http://code4app.net/ios/Static-column-table/50fe649d6803fa7b65000001

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!

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