I got this code in my UITableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"Cell2";
GamesInfoTableViewCell *cell = (GamesInfoTableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
GameInfo *gameInfoObject;
gameInfoObject =[LiveGamesArray objectAtIndex:indexPath.row];
if ([gameInfoObject.GameTime isEqual: #"FT"] | ([gameInfoObject.GameTime rangeOfString:#":"].location != NSNotFound)){
--------------> What to do here? <----------------------------
}
cell.backgroundColor = TABLECOLOR;
cell.homeTeamLabel.textColor = TEXT;
cell.awayTeamLabel.textColor = TEXT;
cell.gameTimeLabel.textColor = TEXT;
cell.liveButton.image = [UIImage imageNamed:#"1675447.png"]; //Load the green image
cell.awayTeamLabel.text = gameInfoObject.AwayTeam;
cell.homeTeamLabel.text = gameInfoObject.HomeTeam;
cell.homeTeamScoreLabel.text = gameInfoObject.HomeScore;
cell.awayTeamScoreLabel.text = gameInfoObject.AwayScore;
cell.gameTimeLabel.text = gameInfoObject.GameTime;
// Configure the cell...
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
So i have a NSMutableArray that contains some objects. And i would only like to populate the table cells with some of the objects. The If statement checks that and if its true then i would like it to go on with the next object/row in the array. I have tried a couple of things but neither did work. Is the only solution to make another NSMutableArray so i can store the ones i want to populate there and then iterate through that one?
Thanks for all the help!!
Yes, you should, you are filtering the array in cellForRowAtIndexPath, which will be called many times. So what I would recommend is to make the array prepared before you load the table.
The key issue that prevents you from coding this up with a conditional inside cellForRowAtIndexPath is that the row from the index path represents a cumulative value of all items that have not been skipped. Hence you need to consider all values in your array in deciding what to print.
Is the only solution to make another NSMutableArray so i can store the ones i want to populate there and then iterate through that one?
This would be a good solution. This is much better than an alternative of traversing the array from the beginning each time, counting the matching objects until you skip row-1 objects, and taking the next one.
Another alternative is building a translation table - i.e. an array of indexes that maps a row to the index in the original NSMutableArray. You can build this table in the method that supplies the row count to your UITableView, and keep it until the next refresh.
Suppose your NSMutableArray looks like this:
0 1 2 3 4 5 6 7 8 9
N Y Y N N Y N Y N N
Top row shows element index. Y is the item you want to keep; N is the item you don't want to show. Your row count method returns 4 (the number of Ys), and builds a table that looks like this:
0 1 2 3
1 2 5 7
The top row is the index of the index array. The bottom row is the index into the original array. Your cellForRowAtIndexPath code needs to pick
gameInfoObject =[LiveGamesArray objectAtIndex:translation[indexPath.row]];
For row 0, translation[indexPath.row] is 1; for row 1, translation is 2; for row 2, translation is 5, and for row 3 it is 7.
as you say "So i have a NSMutableArray that contains some objects. And i would only like to populate the table cells with some of the objects."so there hould be ideally two arrays, 1.LiveGamesArray, 2. create a new filter array like this:
NSMutableArray * filterArray = [NSMutableArray array];
for (GameInfo *gameInfoObject in LiveGamesArray)//can use predicate also
{
#autorelease{
if ([gameInfoObject.GameTime isEqual: #"FT"] || ([gameInfoObject.GameTime rangeOfString:#":"].location != NSNotFound)) {
[filterArray addObject:gameInfoObject];
}
}
}
3.use this filterArray in all data source/ delegate method of your tableview.
hope it will help you.
Related
I am creating UITableViewCell like this. In that screen, I might have 1 quiz, 2 quiz, etc and 1 poll, 2 polls, etc. It will be dynamic.
As a result, when user scroll up and down, based on data received on my cell, I keep removing previous UIViews and recreating again and again. (I know it is super bad. Now my scrolling got issue.)
NSArray *quizzez = self.cellData[SERVER_QUIZZES];
NSArray *polls = self.cellData[SERVER_POLLS];
NSMutableArray *combinedQuizPoll = [NSMutableArray array];
[combinedQuizPoll addObjectsFromArray:quizzez];
[combinedQuizPoll addObjectsFromArray:polls];
for (UIView *vw in self.quizPollViewCollection) {
[vw removeFromSuperview];
}
for (NSDictionary *quizPollDict in combinedQuizPoll)
{
QuizPollSubView *vwQuizPoll = [QuizPollSubView loadFromNibWithType:QuizPollSubViewNoViewRelated andNavType:self.navType];
[vwQuizPoll setW:CGRectGetWidth(self.frame)];
[vwQuizPoll setDelegate:self];
[vwQuizPoll setData:muQuizPollDict];
[vwQuizPoll setX:0 andY:offset];
[self.contentView addSubview:vwQuizPoll];
offset = CGRectGetMaxY(vwQuizPoll.frame) + 4;
[self.quizPollViewCollection addObject:vwQuizPoll];
}
How shall I make to improve performance? I have studied other similar question in StackOverflow also.
How to make a UITableViewCell with different subviews reusable?
1) I need to have dynamic quiz, poll view (number of quiz, poll will be different for each cell)
2) How can I reference to those view that I created?
First of all I have to say that your approach to use the same cell to put things in a vertical is not the best one. For this kind of situation you should use more than one cell. Something like:
...
DecriptionCell
QuizCell
QuizCell
PollCell
PollCell
PollCell
...
Anyway I'm going to propose you a solution that could help you without change the structure of your UITableView.
Actually I had the same problem a few weeks ago, and I found a very good solution for that.
Basically the main concept is, to Reuse UITableViewCell you shouldn't add or remove views in the configure of the cell because the performance will be affected.
So, the solution that I have used was, use different reuse identifier for each kind of configuration that the cell can have.
The unique requirement is not to have a Nib file for the cell.
If I understood properly your cell can have dynamics Quizs and Polls. Let's go to say that a maximum of 10 Quizs and a Maximum of 10 Polls. Although I'm watching that both have the same View, QuizPollSubView. So let's put a maximum of 20 subviews per cell.
So in the method where you are registering the cells I would do the next:
Class myClass = [CustomTableViewCell class];
NSString *classID = NSStringFromClass(myClass);
for (NSUInteger index = 0; index < 20; index++) {
NSString *identifier = [classID stringByAppendingString:[#(index) stringValue]];
[self.tableView registerClass:myClass forCellReuseIdentifier:identifier];
}
Then in the CellForRow you must dequeue the cell with the properIdentifier, for instance:
NSString *cellID = NSStringFromClass([CustomTableViewCell class]);
NSUInteger numberOfQuizsAndPolls = 3 + 2; //This is 3 quizs and 2 polls, I gess that you can read from the DataModel
NSString *identifier = [cellID stringByAppendingString:[#(numberOfQuizsAndPolls) stringValue]];
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
//then configure the cell
Next, in the initWithStyle:reuseIdentifier: you should create the subviews with empty value, extracting the info from the identifier
NSString *stringNumber = [reuseIdentifier stringByReplacingOccurrencesOfString:NSStringFromClass([self class])
withString:#""];
NSUInteger numberOfSubviews = [stringNumber integerValue];
//here you should add all of your QuizPollSubView with emtpy content.
for (NSUInteger index = 0; index < numberOfSubviews; index++) {
QuizPollSubView *vwQuizPoll = [QuizPollSubView loadFromNibWithType:QuizPollSubViewNoViewRelated andNavType:self.navType];
[vwQuizPoll setW:CGRectGetWidth(self.frame)];
[vwQuizPoll setDelegate:self];
//[vwQuizPoll setData:muQuizPollDict]; YOU CAN NOT SET THE DATA HERE BECAUSE YOU DONT HAVE IT
[vwQuizPoll setX:0 andY:offset];
[self.contentView addSubview:vwQuizPoll];
offset = CGRectGetMaxY(vwQuizPoll.frame) + 4;
[self.quizPollViewCollection addObject:vwQuizPoll];
}
Finally you must to set the proper information in the configure of the cell. Something like:
- (void)configureWithQuizPollDict:(NSDictionary *)combinedQuizPoll
{
for (NSDictionary *quizPollDict in combinedQuizPoll)
{
//get the proper index in the quizPollViewCollection.
QuizPollSubView *vwQuizPoll = self.quizPollViewCollection[index];
[vwQuizPoll setData:muQuizPollDict];
}
}
I hope that it helps you!!
Thanks
PD: If you want to use a Cell with Nib probably we need to subclass the UITableView to add custom dequeue
i am newbie to iOS and making a cart screen having a table view each cell with two buttons one of them to add quantity and other to choose variant in the particular cell, i want to make an array of the no. of objects chosen in the table view of last updated quantity and if two different variants are chosen there should be two objects with their selected variants and their individual quantities too in array
-(void)addQuantityMethod:(id) sender
{
ItemSelectTableViewCell *clickedCell = (ItemSelectTableViewCell *) [[sender superview] superview];
quantity = [clickedCell.qtyDisplayLbl.text intValue];
NSIndexPath *clickedButtonPath = [self.subMenuTblView indexPathForCell:clickedCell];
if (clickedButtonPath)
{
clickedCell.qtyDisplayLbl.text = [NSString stringWithFormat:#"%d",++quantity];
}
[self.selectedDict setObject:clickedCell.itemNameLbl.text forKey:#"pName"];
[self.selectedDict setObject:clickedCell.itemPriceLbl.text forKey:#"unitPrice"];
[self.selectedDict setObject:clickedCell.lblSelectVariant.text forKey:#"variant"];
[self.selectedDict setObject:clickedCell.qtyDisplayLbl.text forKey:#"qty"];
if anyone could help me out then please its being appears very much complicated for me to deal with as i am newbie.Thanks in advance
I have an app that used to work before I upgraded to XCODE 5. I needed to find the row that was selected for a structure I was displaying which has over 100 rows so obviously can be scrolled on the display. The code that used to work is:
NSIndexPath *indexPath = [self.mainTableView indexPathForCell:myCell];
NSInteger row = [indexPath row];
Now, regardless of the row selected, the value of row is always 0. Anyone have any suggestions for me? Thanks.
This worked for me...
CGPoint pos = [pressedButton convertPoint:CGPointZero toView:self.mainTableView];
NSIndexPath *indexPath = [self.mainTableView indexPathForRowAtPoint:pos];
NSInteger row = [indexPath row];
Remember that in Objective-C, you can always send a message nil, and methods that return something (i.e., not void) will return either nil(for an object) or 0 (for a value) when sent to nil (for structs, it is more complicated; read this).
So make sure that:
self.mainTableView is not nil
indexPath is not nil
hi I am working on with collection view for a calendar. I put a label in the collection view. I give the value to this label from a static array in which I add the months name. Now I have to change the color of label according to the value 0 and 1. if 1 then label turn into green and if 0 then red. These 0 and 1 values I got form the JSON. I put these values in the array.
Now my problem when I use this array in cellForItemAtIndexPath then its crash because the count of rows is 12 and the count of valueArray is 2. Is there any way to work with this. thanks..!
The problem is inconsistency in your data model.
1) Wherever your data is coming from (network, JSON..etc.) you need to end up with NSDictionary of key value pairs.
Key - month
Value - red or blue
2) Then in collectionView:numberOfItemsInSection: you should return number of items in dictionary like this
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [dictionary allKeys] count];
}
3) In your ViewController create a month mapping array. Simple NSArray that will contain 12 NSStrings - your months.
-(NSArray *)months
{
return #[#"january",
#"february",
#"march"
#"april",
#"may",
#"june"
#"july",
#"august",
#"september",
#"october",
#"november",
#"december"];
}
4) Finally you will handle your concrete item in didSelectItem... by retrieving a month for a particular index..and then setting the cell to match the value for that month...and based on value you will set the color.
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
//....other code here
NSString *month = self.monthsArray[indexpath.row];
NSString *value = self.monthsDictionary[month];
if (value isEqualToString:#"red")
{
coolectionViewCell.color = [UIColor redColor];
}
etc..
BONUS:
You did not say what red and green means, but you really should declare an enumeration for that thing as this is a custom type. You would wrap your enums in the dictionary as NSNumbers.
Also the month mapping array is kind of rudimentary but I did not want to overwhelm you. I am sure NSDateFormatter has some kind of mechanism to play with months in a comprehensive localised way.
I am using TLIndexPathCollapsible.
Link: https://github.com/wtmoose/TLIndexPathTools
Now I have 2 sections (A and B), 3 rows for each section (a b c). If I expand A and B and I use this:
NSInteger rowNumber = 0;
for (NSInteger i = 0; i < indexPath.section; i++) {
rowNumber += [self tableView:tableView numberOfRowsInSection:i];
NSLog(#"number: %ld",(long)rowNumber);
NSLog(#"rows in previous section %ld",(long)[tableView numberOfRowsInSection:i]);
}
rowNumber += indexPath.row;
It works.
But when I collapsed section A and tap on (section B row a). Because the previous section (section A) is collapsed and has no rows therefore, it returns 0.
I am using one array to store.
How do i loop through section A and + 1 to get indexPath.row =3?
The idea with TLIPT is that you use a TLIndexPathDataModel to store your data items and then the TLIndexPathDataModel APIs let you easily convert indexPaths to data item and vise versa. So if you're using TLCollapsibleTableViewController, you'd do something like this:
id myDataItem = [self.indexPathController.dataModel itemAtIndexPath:indexPath];
If you need to find the index in an external array, then you can do this:
NSInteger index = [myArray indexOfObject:myDataItem];