Load cells in UITableView - ios

I have UITableView with cells, i use footer(height = 10pt) for each sections, header (height = 64pt) for each sections and cell (hight = self.view.frame.size.hight - 64 - 10).
TableView loads only first cell, when i launch app (because second cell is not visible on screen), but i want to load first and next cell. And when i scroll to second row i want to load third cell.
How can i achieve this?

UITableView delegate methods provide you several ways to track which cell just appeared on screen (i.e. tableView:willDisplayCell:forRowAtIndexPath:).
One way to do it is to track which cell was displayed, and load +1 and/or -1 indexes manually.
Note: you shouldn't load the UITableViewCells directly but the content they are supposed to show (according to M.V.C).

lazy-loading suit for you, which means first is visible, when scroll down second item should be ready.
//Store all items
NSArray *allItems = #[].mutableCopy;
//Load first two and store into allItems
NSDate *first, *second;
allItems = #[first,second];
//Check which cell is visible when scroll down and if the data has been ready
1) path.section is the visible cell
NSIndexPath *path = [tableView indexPathForCell:aCell];
2) allItems count is the number of data you have loaded
allItems.count = path.section + 1;
3) If allItems.count == path.section, you should load the next data, which is next of the current visible one.
By these two conditions the data should be ready all the time.
After each load [tableView reload] to display.

Related

Can not access cells on uitableview's sections which not displaying on screen

I am having trouble with dequeueReusableCellWithIdentifier
I have a tableview with multiple sections. All sections have dynamic rows and all rows have some form fields. The last sections row count is increasing or decreasing depending on the form fields of the other sections.
I am accessing the cells of last section with following code:
let indexPath = NSIndexPath(forRow: remarkCount, inSection: clsections.count )
let cell = tableView.cellForRowAtIndexPath(indexPath) as! remarkCell!
is this sample tableview has 10 sections.
the problem is ;
if the section 10 is visible on iPad's screen (simply scroll down to bottom of tableview), cell will be created as! remarkCell! Otherwise cell will be nil.
Should I programmatically scroll to bottom of tableview before using cellForRowAtIndexPath? Or is there any alternate methods to dequeueReusableCellWithIdentifier without re-using cells ?
Thank you.
CellForRowAtIndexPath will be called automatically when needed (when the cell is about to be visible).
When you use dequeueReusableCellWithIdentifier, it will "recycle" an existing cell if possible, or create a new one if not

UICollectionView Cells Are Not Retaining Data --- How Can I Make Their Data Persistent?

I have a UICollectionView full of custom cell objects.
When the user selects one I draw a circle and put a number in the middle.
However as the user scrolls down and then back up, selected cells have their number data all messed up.
I dove deeper into what the problem is, and it turns out that cells are not cached, and when you scroll up with a UICollectionView, its creating new cell assets, as such data inside them is destroyed (and hence I can't store a number in them). So my thought is to put the number back each time that cell is back on the screen, but I can't tell when a cell is being displayed or not.
I've made a map which records the NSIndexPath of selected cells. However, I don't know how to tell if that path (i.e. a cell at that path) is currently being displayed.
Do you know how I can tell if a cell is being displayed from an NSIndexPath at any point along a scroll?
Here is my cell code for selection (my UICollectionView calls this).
override public var selected: Bool
{
didSet
{
_checkMark?.hidden = !selected
_number?.hidden = !selected
println("did set")
}
}
func setNumberText(number:UInt8)
{
if(_number == nil)
{
_number = UILabel(frame: CGRectMake(0,0,1,1))
addSubview(_number)
}
_number.text = String(number)
_number.sizeToFit()
_number.frame = CGRectMake(_checkMark.frame.width/2 - _number.frame.width/2, _checkMark.frame.height/2 - _number.frame.height, _checkMark.frame.width, _checkMark.frame.height)
_numberInt = number
}
Is there some "cellAtPathIsNowOnScreen" event I can track?
You're doing it wrong. Cells get reused as you scroll, and the method by which this happens is an implementation detail that you don't get to know.
Instead you should store the data about what the cell should draw, in this case the number, in the data source for your collection view. Then in -
collectionView:cellForItemAtIndexPath: you can tell the cell what number to draw after you dequeue it, or clear the value if the number shouldn't be drawn for this particular cell.
Additionally, UICollectionView does have a - visibleCells method which will return an array of all the cells that are currently visible, but that's really not what you want to do.

UITableView dynamic content loading when scrolling

I'm trying to implement an infinite UITableView. I load some information from the server in chunks and I want to dynamically add this information to the tableview when user scrolls the table.The problem I'm facing : I have an initial tableview with 40 elements and then in scrollViewDidScroll I check if last visible row's indexPath == [myData count] - 20 (so when user has already scrolled half of the list I load next content) I load next 40 elements of content from the server and only when last visible row's indexPath == [myData count] -1 I actually reload the tableview. So as you see i make some eager caching in order to make tableview reloading faster.Everything work perfectly but when I begin to scroll my table really fast data stopped loading. It seems that this check: last visible row's indexPath == [myData count] - 20 has actually no chance to implement because of fast scrolling.I can't see any other obvious reasons for this. So has someone some answer for this weird problem?
P.S. Or may be I should try reloadRowsAtIndexPaths instead of reloading the whole table?
Maybe with this delegate you have a chance to do something in advance. There is also possible to reload only the visible rows which it's better than reload data.
-(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
NSArray *paths = [self.tableView indexPathsForVisibleRows];
int tmprow = [[paths objectAtIndex:0] row];
}

How to access first and last cells of UITableView

I have a UITableView with custom cells,, I want to set background images of those custom cells. The background image of first and the last cell of the UITableView should be different than other cells.
I have used dequeueReusableCellWithIdentifier: to create the cell.
to set the background images of the first cell, I wrote
`
if (indexPath.row==0) {
cell.cellBackgrounfImage.image=[UIImage imageNamed:#"TopCellImage.png"];
}
`
1) Because of the reusing cell,,, this is going to set middle cell image rarther than the first cell. How can I overcome this problem
2) How to access the last cell of the UITableView to set other image
Please anyone give me a solutions for these 2 questions.
Thanks
For Step 1)
When you are scrolling tableview, it will be always reload data. So may be it will generate background image for middle one.
But, if you are set indexpath.row == 0 condition, then it will not affect any row instead of first one.
For Step 2)
You can get values for no of arrays (Array Count).
suppose int totalArr = [arr count];
Then apply condition same as first row by,
if(indexpath.row == (totalArr - 1) {
cell.cellBackgrounfImage.image=[UIImage imageNamed:#"BottomCellImage.png"]; }
So, it will work for last one also.
Thanks.

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