UITableViewCell - Updating NSMutableDictionary Values - ios

I have UITableViewController and it has twitter like post with like buttons. what im doing is when ever like button clicked if it is success trying to update the like count by + 1. i did the all the the above method except for the update part.
im getting Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object' Error.
Here is my code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
FeedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSDictionary *feedList = [liveFeeds objectAtIndex:indexPath.row];
//liveFeeds is NSMutableArray
cell.likeCount.text = [feedList objectForKey:#"likes"];
cell.like.tag = indexPath.row;
[cell.like addTarget:self action:#selector(likeClicked:) forControlEvents:UIControlEventTouchUpInside];
}
-(void) likeClicked:(UIButton*)sender{
//Here im using AFNetworking and getting JSON response.
//After that im doing following to update the like
NSMutableDictionary* feedList = [liveFeeds objectAtIndex:sender.tag];
NSString *oldLike = [feedList objectForKey:#"likes"];
int newLike = [oldLike intValue] + 1;
NSString *strFromInt = [NSString stringWithFormat:#"%d",newLike];
NSLog(#"updated like %#",strFromInt); // up to this it works
[feedList setObject:strFromInt forKey:#"likes"]; // in here it get crashe
[self.tableView reloadData];
}
What i want to do is. liveFeeds Array update with that Like Count and reload the table. am i doing this wrong? or is there any easy way to do this?

Most likely [liveFeeds objectAtIndex:sender.tag] is a NSDictionary, not an NSMutableDictionary. So you cannot change its content.
Build feedlist with the content of [liveFeeds objectAtIndex:sender.tag] :
NSMutableDictionary* feedlist = [NSMutableDictionary dictionaryWithDictionary:[liveFeeds objectAtIndex:sender.tag]]

I haven't tried it yet but i guess you're trying to use a NSMutableDictionary method on a NSDictionary.
Try changing:
NSMutableDictionary* feedList = [liveFeeds objectAtIndex:sender.tag];
To:
NSDictionary* dic = [liveFeeds objectAtIndex:sender.tag];
NSMutableDictionary* feedList = [NSMutableDictionary alloc] initWithDictionary:dic]];

Simply create mutable copy of NSDictionary. Actually NSMutableDictionary* feedList = [liveFeeds objectAtIndex:sender.tag] returns NSDictionary. So to make it editable you have to create another copy which is mutable by using mutableCopy. NSMutableDictionary* feedList = [[liveFeeds objectAtIndex:sender.tag]mutableCopy]
-(void) likeClicked:(UIButton*)sender{
//Here im using AFNetworking and getting JSON response.
//After that im doing following to update the like
NSMutableDictionary* feedList = [[liveFeeds objectAtIndex:sender.tag]mutableCopy];
NSString *oldLike = [feedList objectForKey:#"likes"];
int newLike = [oldLike intValue] + 1;
NSString *strFromInt = [NSString stringWithFormat:#"%d",newLike];
NSLog(#"updated like %#",strFromInt); // up to this it works
[feedList setObject:strFromInt forKey:#"likes"]; // in here it get crashe
[self.tableView reloadData];
}

Related

Array of array in Objective-C

i have a NSArray of twitter_timeline using this tutorial http://tutorials.veasoftware.com/2013/09/20/twitter-api-version-1-1-user-timeline-in-ios-7/
I get my timeline using this code on cellForRowAtIndexPath method:
NSdictionary *tweet=_twitter_feed[indexPath.Row];
cell.labeltext.text=tweet[#"text"];
Everything works fine, BUT i want to create another array (NSMutableArray) and insert my _twitter_feed(NSArray) into it and get the same access to twitter_feed.
Something like that:
NSMutableArray *mainarray=[[NSMutableArray alloc]init];
[mainarray addObject:_twitter_feed];
but i don't know how to get text from twitter_array from main array
NSDictionary *tweet=[[mainarray objectAtIndex:0]indexPath.row];//??????
cell.labeltext.text=tweet[#"text"];
This is doesn't work.
If the _twitter_feed is a NSArray, you can simply use [[mainarray objectAtIndex:0] objectAtIndex:indexPath.row] to get it.
Try using NSMutableDictionary: (untested)
NSMutableDictionary *mainDict= [NSMutableDictionary dictionary];
[mainDict setObject: _twitter_feed forKey:[NSString stringWithFormat:#"%#", indexPath.row]];
and retrieve like:
NSdictionary *tweet= [mainDict objectForKey:[NSString stringWithFormat:#"%#", indexPath.row]];
cell.labeltext.text=tweet[#"text"];
Consider the line that is giving you the error:
NSDictionary *tweet = [[mainarray objectAtIndex:0]indexPath.row];
Now you've added the reference stored in _twitter_feed into the your mainarray, so this line is effectively:
NSDictionary *tweet = [_twitter_feed indexPath.row];
Compare this to your working line:
NSDictionary *tweet = _twitter_feed[indexPath.row];
Those two are not the same. Maybe you meant to type:
NSDictionary *tweet = [mainarray objectAtIndex:0][indexPath.row];
You can shorten that to:
NSDictionary *tweet = mainarray[0][indexPath.row];
HTH

Add a field to each object inside an array

I'm parsing XML data of a third party provider.
They include all the information i need for each Team, except their logo.
I have all the logos imported into my project.
Is there a way to add a logo field to each team?
This is my parse method, works perfectly
-(void) parseXML{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"apikeygoeshere"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *xmlString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *xml = [NSDictionary dictionaryWithXMLString:xmlString];
NSMutableArray *items = [xml objectForKey:#"TeamLeagueStanding"];
NSString *nullentry = #""; // custom code for specific reason
NSString *nullentry2 = #""; // custom code for a specific reason
[items insertObject:nullentry atIndex:0]; // custom code for a specific reason
[items insertObject:nullentry2 atIndex:1]; // custom code for a specific reason
[self setTableData:items];
}
This is my cellForRowAtIndexPath method, as you will see my logos are being feed from an array that i have inside my code, but if the team that is in 1st place drops to 2nd, the logos won't change position
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"StandingsIdent";
StandingsViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSDictionary *item = [tableData objectAtIndex:[indexPath row]];
if ([item isKindOfClass:[NSDictionary class]]) {
long row = [indexPath row];
cell.cellTeamName.text = [item objectForKey:#"Team"];;
cell.cellTeamLogo.image = [UIImage imageNamed:_teamLogos[row]];
cell.cellTeamPosition.text = _teamPosition[row];
cell.cellPlayed.text = [item objectForKey:#"Played"];
cell.cellWins.text = [item objectForKey:#"Won"];
cell.cellTies.text = [item objectForKey:#"Draw"];
cell.cellLoses.text = [item objectForKey:#"Lost"]; ;
cell.cellPoints.text = [item objectForKey:#"Points"];
cell.cellInfo.text = _infoLeague[row];
}
else {
}
}
Is it possible to somehow add these logos to each team? so when team "x" moves the logo does too.
Here is the xml data structure after being parsed:
{
Draw = 10;
"Goal_Difference" = "-17";
"Goals_Against" = 39;
"Goals_For" = 22;
Lost = 11;
NumberOfShots = 395;
Played = 25;
PlayedAtHome = 13;
PlayedAway = 12;
Points = 22;
RedCards = 5;
Team = Partick;
"Team_Id" = 561;
Won = 4;
YellowCards = 41;
}
Thanks ;)
You receive an NSDictionaryfor each team - this is an immutable object so you can't change it. But, you can create a mutable copy of it (so you will have an NSMutableDictionary).
When you do:
NSMutableArray *items = [xml objectForKey:#"TeamLeagueStanding"];
it's unlikely that you actually get a mutable array back (though you might). Again though, you can create a mutable copy if not.
Then, iterate through the teams, create a mutable copy of the dictionary, add the key/value pair that you need for the logo and then replace the original entry in the array with your updated copy.
Or, an alternate approach:
Store your logos in a different dictionary, where the keys are the team names (or unique ids) and the values are the logo image names. Then, instead of _teamLogos[row] you would use _teamLogos[[item objectForKey:#"Team"]] to get the image name.

Xcode NSDictionary Subdictionary

I have dictionary which i want to use to fill a tableview. It is parsed by JSON.
My dictionary looks like that:
NSLog(#"%#",temp);
// OUTPUT //
(
{
ShootingDate = "2013-07-29 00:00:00";
ShootingID = 1;
ShootingName = Testshooting;
},
{
ShootingDate = "2013-06-12 00:00:00";
ShootingID = 2;
ShootingName = Architektur;
}
)
Dictionary looks in XCode like that:
Now i want to fill a table with that data. Each row should display ShootingDate,ShootingID and ShootingName but i am not able to access these keys.
Anyone a suggestion?
First of all temp is not dictionary it is NSArray and u can get it as
for (NSDictionary *dictionary in temp) {
[dictionary valueForKey:#"ShootingDate"];
[dictionary valueForKey:#"ShootingID"];
[dictionary valueForKey:#"ShootingName"];
}
You can get your dictionary in cellforRow as
NSDictionary *tempDicts=[temp objectAtIndex:indexPath.row];
cell.textLabel.text=[NSString stringWithFormat:#"id=%#,date=%#,name=%#",[tempDicts valueForKey:#"ShootingID"],[tempDicts valueForKey:#"ShootingDate"],[tempDicts valueForKey:#"ShootingName"]];
you can access these keys as
NSString *str_ShootingDate = [[temp objectAtIndex:indexpath.row]
objectForKey:#"ShootingDate"]; //you can change this key with ShootingID
//or ShootingName

-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0x91da0f0

when i set the value in nsmutabledictionary then given error show in image below....
here my code for setvalue in nsmutabledictionary
NSMutableArray *countArray=[[NSMutableArray alloc] init];
for (int i=0;i<artistName.count;i++)
{
int count=0;
NSMutableDictionary *dir1=[artistName objectAtIndex:i];
NSString *artist1=[dir1 objectForKey:#"SONG_ARTIST"];
for (int j=0;j<CurrentPlayingSong.count;j++)
{
NSDictionary *dir2=[CurrentPlayingSong objectAtIndex:j];
NSString *artist2=[dir2 objectForKey:#"SONG_ARTIST"];
if ([artist2 isEqualToString:artist1])
{
count++;
}
}
NSString *Size=[[NSString alloc] initWithFormat:#"%d",count];
[dir1 setObject:Size forKey:#"SIZE"];
[countArray addObject:dir1];
}
return countArray;
this NSMutableDictionary *dir1=[artistName objectAtIndex:i]; returns a NSDictionary object which turns your dir1 to the same type.
best way is to do something like this:
NSMutableDictionary *dir1=[NSMutableDictionary dictionaryWithDictionary:[artistName objectAtIndex:i]];
or
NSMutableDictionary *dir1 = [artistName[i] mutableCopy];
This will ensure that dir1 will always be NSMutableDictionary.
hope this helps

objectForKey crash? iOS

I am trying to use the following code to load a UIButton and UITextField with information based upon a UISegmentedControl's current segment that is clicked but it is causing a SIGABRT crash.
Here is the code:
- (void)updateInfo {
NSLog(#"count1:%d", [self.accounts count]);
[self saveInfo];
NSLog(#"count2:%d", [self.accounts count]);
NSDictionary *dict = [self.accounts objectAtIndex:0];
NSData *imageData = [dict objectForKey:#"ProfileImage"];
UIImage *imageProfile = [UIImage imageWithData:imageData];
[image1 setImage:imageProfile];
NSDictionary *dict2 = [self.accounts objectAtIndex:1];
NSData *imageData2 = [dict2 objectForKey:#"ProfileImage"];
UIImage *imageProfile2 = [UIImage imageWithData:imageData2];
[image2 setImage:imageProfile2];
if ([self.accounts objectAtIndex:accountSC.selectedSegmentIndex] != nil) {
NSDictionary *dict = [self.accounts objectAtIndex:accountSC.selectedSegmentIndex];
//NSString *name = [dict objectForKey:#"Name"];
NSString *name = [accountSC titleForSegmentAtIndex:accountSC.selectedSegmentIndex];
[Name setText:name];
NSData *imageData = [dict objectForKey:#"ProfileImage"];
UIImage *imageProfile = [UIImage imageWithData:imageData];
[pictureButton setImage:imageProfile forState:UIControlStateNormal];
}
else {
Name.text = nil;
[pictureButton setImage:nil forState:UIControlStateNormal];
}
}
The first & second big block of code is temporary because I wanted to see the UIImage's based upon different objectAtIndex numbers.
Here is the console crash log:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString objectForKey:]: unrecognized selector sent to instance 0x2cc08'
Any reason why this can be happening? Do I need to post any other code I am using?
I really need help on this, I have been pulling my hair out!!!
Edit1:
I am using this code, also you were talking about isKindOfClass right?
Anyway this is the code:
NSDictionary *dict = [self.accounts objectAtIndex:1];
if ([dict isKindOfClass:[NSDictionary class]]) {
NSLog(#"YES");
}
else {
NSLog(#"NO");
}
Im testing now...
You're sending objectForKey: to an NSString object, specifically one that you've typed directly into your code somewhere in #"..." form rather than one you've created programmatically (or had created programmatically for you). Someone is putting something other than a dictionary into self.accounts.
NSDictionary: objectForKey:
objectForKey: returns the value associated with key, or nil if no value is associated with key.
key :A string identifying the value. If nil, just return nil.
(1)you should know the key is not blank
(2)you should know the object is not blank and the objects are the same type ,because you shouldn't use different kinds of type in a NSDictionary.
e.g. {#"key1":NSString,#"key2":NSArray} //this is a demonstration of error

Resources