avoid adding duplicate object in dictionary and array of dictionaries ios - ios

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

Related

iOS Adding dynamic subview into uitableviewcell

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

How to check if table view cells subtitles are equal to each other iOS

I'm wondering if there is a way to check if a cell's detailTextLabel.text is equal to another cell's detailTextLabel.text.
The reason for this is I would like to set the detailTextLabel.textColor to the same color if the cells texts are equal to each other.
For instance, if there are multiple cells with the same subtitle - lets say I have three cells with a subtitle that say pizza - Id like to set the color for pizza to green.
I fear that adding my code might make things a bit more confusing, as I pull the subtitle from core data based on the user's search text (there's just alot going on as I also persist to core data from a data source). So the subtitles themselves are, in a way, random. My app essentially lets a user search for points of interests based on a category. So if the user searches for pizza, the map view will display any local restaurants that serve pizza. You're then able to save that specific point of interest and the subtitle is set to pizza (or whatever the user searched for). So it's possible to have multiple entries that have the subtitle pizza (if the user saves multiple points of interest based on the 'pizza'.)
Try and forget the logistics of setting the color, I'd really just like to know how I could check if the subtitles are equal to each other in a TableView. I should specify that we are not checking if the actual text is equal to a specific string:
Not:
if(cell.detailTextLabel.text == #"pizza"){
cell.detailTextLabel.textColor = randomColor;
}
Something like this
if(cell.detailTextLabel.text == some other detailTextLabel){
cell.detailTextLabel.textColor = randomColor;
}
Core Data Example
self.category is my NSManagedObject. In this case I've already been able to persist a randomly generated color to core data. All I really need is the logic to set the color equal to the subtitles that have also been persisted to core data.
-(void)configureCell:(CategoryTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath{
//fetch record
NSManagedObject *record = [self.fetchedResultsController objectAtIndexPath:indexPath];
self.category = [self.fetchedResultsController objectAtIndexPath:indexPath];
float red = [self.category.red floatValue];
float green = [self.category.green floatValue];
float blue = [self.category.blue floatValue];
UIColor *randomRGBColor = [[UIColor alloc] initWithRed:red green:green blue:blue alpha:1.0];
//update cell
[cell.textLabel setText:[record valueForKey:#"name"]];
cell.backgroundColor = randomRGBColor;
}
I think your approach is wrong. Why should you compare strings in cells rendered and not before it even started rendering. When you create your UITableView you have certain datasource, at least array of NSString (titles).
You can implement a render method in which you loop through the array of titles, find equals and create new array of NSDictionary for example, where for key #"title" you have your title and for key #"color" you have already calculated colour. And in your tableView:cellForRowAtIndex method you just get the colour from array and assign to UITableViewCell instance together with assigning text to detailTextLabel.
You could do something like this with a dictionary in your data layer, where you associate the subtitles with a specific color.
var dict = [String: UIColor]
...
if let color = dict[subtitle] {
//set the color of the cell
} else {
let newColor = //some color you haven't used yet
dict[subtitle] = newColor
}

change the color of label in UICollectionView iOS

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.

Skipping rows when iterating through NSMutableArray in TableView

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.

iPhone - how to select from a collection of UILabels?

I have a few UILabels, any one of which will update according to the index of an NSArray index they represent. I thought of selecting them by their tag
self.displayLabel.tag = myArray[index];
but that changes the tag value to whatever my array is holding at the moment
Using a dictionary for whatever tricks it offers instead of an NSArray doesn't help because i still have to select the correct matching label. This is the effect i want to achieve.
self.|mySelectedLabel|.text = myArray[index];
what should i put in |mySelectedLabel| to get the one i'm looking for?
I'm almost ashamed to ask at my reputation level, but this is stymie-ing me
every search only turns up how to set Labels and change, not the process of selecting
Assuming you have set the tags to the appropriate index to match your
array indices you can use [self.view viewWithTag:index];
Why are you not setting the tag with:
self.displayLabel.tag = index;
Also, you could just loop though an array of labels and find the right one:
for (UILabel *label : labelArray) {
if (label.tag == index) {
label.text = #"I found you!";
}
}
Rather than using tags you can refer to your specific textfields by reference:
// Create an array to hold your textfields
NSMutableArray *textFields = [NSMutableArray array]
// Create your textfields and add them to the array
UITextField *textField;
for (NSUInteger idx = 0: idx++; idx < numberOfTextFieldsYouWant) {
textField = [UITextField alloc] initWithFrame:<whateverYouWant>];
[textFields addObject:textField];
}
Since you are adding the objects to an array, rather than using the tag value 0, 1, 2... you can just access it by it's index in the array
So, for what you want to do you can just do:
textfields[index].text = myArray[index];
It's a lot cleaner, doesn't rely on magic tags, and you have an array of all your dynamic textfields that you can remove, or change in one place.
I think tags are vastly overused, and they aren't necessary in most cases.
Just letting you know I reframed the problem and this eventually worked for me without having to use an array
( with endless experimenting, I sort of bumped into it so I don't know if it constitutes good technique )
the desired label corresponding to the bag weight ( one of a number possible ) displays the right update
- (IBAction)acceptWeight:(UIButton *)sender {
int tempValue = (int) currentWeight;
// current weight comes from a UISegementedController
for (UILabel *labels in self.view.subviews)
{
if (labels.tag == currentWeight)
{
bags[tempValue]++;
labels.text = [NSString stringWithFormat:#"%i",bags[tempValue]];
}
}
totalKilo = totalKilo + (int)currentWeight;
self.totalKilo.text = [NSString stringWithFormat:#"%d",totalKilo];
}

Resources