How to get object value from NSMutableDictionary? - objective-c

I have this bit of code where I put objects into a NSMutableDictionary:
SingletonDictionary *sd = [SingletonDictionary sharedDictionary];
UITextField *tf = (UITextField *)sender;
int tagValue = tf.tag; // get the tag value
[sd.dictionaryOfUserIndexes setObject:tf.text forKey:[NSString stringWithFormat:#"%d", tagValue]]; // value found in textField id'd by tag
UPDATED: This is the code where I'm trying to retrieve the contents of the dictionary:
SingletonDictionary *sd = [SingletonDictionary sharedDictionary]; // initialize
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // here too...
sd.dictionaryOfUserIndexes = [defaults objectForKey:#"importFileIDs"]; // move from standardUserDefaults to dictionary singleton
NSLog(#"\n\nsd.dictionaryOfUserIndexes: %#", sd.dictionaryOfUserIndexes);
[sd.dictionaryOfUserIndexes[intTagValue]]]; // move contents of textField from dictionary
textField.text = [sd.dictionaryOfUserIndexes objectForKey: tagValue];
This is the contents of sd.dictionaryOfUserIndexes:
sd.dictionaryOfUserIndexes: {
0 = 2;
1 = 5;
2 = 8;
4 = 7;
}
The first column is the tag of the UITextField; the 2nd column is the data in that textField
The contents of the dictionary are valid; I got rid of the build errors, but when I run this, there is nothing in the textField.
I have looked and looked at this, and just hope I didn't do something stupid. Can someone please tell me what's wrong?

I figured it out...
textField.text = [sd.dictionaryOfUserIndexes objectForKey: [tagValue stringValue]];
Thanks everybody for your time; I appreciate it.

Related

Values changing automatically

Hi together I have a Problem:
I read out the actual Values of the Playing media song, and add it to a dictionary.
And then into an Array. If I add a new entry pressing the Button again, all Values of all entrys changing to the same.
Do you have an Idea why?
Here my Code:
- (IBAction)ActionButtonLU:(id)sender
{
MPMediaItem *currentItem = [musicPlayer nowPlayingItem];
NSString *titleString = [currentItem valueForProperty:MPMediaItemPropertyTitle];
NSString *artistString = [currentItem valueForProperty:MPMediaItemPropertyArtist];
NSString *albumString = [currentItem valueForProperty:MPMediaItemPropertyAlbumTitle];
if (titleString == nil) {
titleString = #"";
}
if (artistString == nil) {
artistString = #"";
}
` `if (albumString == nil) {
albumString = #"";
}
[_dictCat1 setObject:titleString forKey:#"Titel"];
[_dictCat1 setObject:artistString forKey:#"Artist"];
[_dictCat1 setObject:albumString forKey:#"Album"];
[_countCat1 addObject:_dictCat1];
[musicPlayer skipToNextItem];
}
You are modifying the same dictionary, _dictCat1, in every call. You need to create a dictionary locally and add that to _countCat1.
[_countCat1 addObject:#{ #"Title": titleString,
#"Artist": artistString,
#"Album": albumString }];
When you add an object to a collection (NSArray, NSDictionary, NSSet etc, including mutable counterparts), the collection doesn't copy it. With [_countCat1 addObject:_dictCat1]; you keep adding the same object to _countCat1 over and over. You need to create new NSDictionary and add that to _countCat1 collection.

Array Issue in Objective C Xcode

I have a problem with my algorithm for calculating a sore. The user enters a word into the UITextField, and if the word matches a string in the array (#"The Word") the int 'score' will be added by 1.
Then the int score is set as a label as the user gets a word right. (DISPLAYING THE SCORE)
THE PROBLEM, a user can just keep on entering the same word over and over again and the score will keep going up by one. IS there a command for knowing if a word has already been entered, so you can only use the word once.
The Code
NSArray *scoreArray1 = [NSArray arrayWithObjects:
#"Word 1", #"Word 2", #"Word 3", nil];
NSString *inputtwo =_EnterNameText.text;
BOOL isItright = NO;
for(NSString *possible in scoreArray1) {
if([inputtwo isEqual:possible] ) {
isItright = YES;
break;
}
}
if(isItright) {
static int myInt = 0;
myInt++;
NSString *score = [NSString stringWithFormat:#"%d", myInt];
[_scorelabel setText:score];
}
UPDATE!!!!!!
NSArray *scoreArray1 = [NSArray arrayWithObjects:
#"Alan Shearer", #"Shearer", #"Andrew Cole", #"Andy Cole", #"Cole", #"Thierry Henry", #"Henry", #"Robbie Fowler", #"Fowler", #"Frank Lampard", #"Lampard", #"Michael Owen", #"Owen", nil];
NSSet *set2 = [NSSet setWithArray:scoreArray1];
NSString *inputtwo =_EnterNameText.text;
BOOL isItright = NO;
for(NSString *possible in set2) {
if([inputtwo isEqual:possible] ) {
isItright = YES;
break;
}
}
if(isItright) {
static int myInt = 0;
myInt++;
NSString *score = [NSString stringWithFormat:#"%d", myInt];
[_scorelabel setText:score];
}
HOWEVER NOW THE APP DOES NOT WORK, IT CRASHES, any suggestions?
Why don't you keep a second Array where you store the given (correct) answers.
Whit this you can just do a contains inside your if....problem solved.
a second option is not to put string in your array but "Answer" Objects, that have a field that you can flag as already used.
You could just create an NSMutableSet and put a copy of the word into there whenever one is entered. Then you just need to check if the word exists in the set before incrementing the score.
I'm suggesting a set because it uses hashed access, so lookups are fast. Also, if you add the same string more than once, the set will still only have one reference to the string.
Actually, if you have an array of "legal" words, the way to go is to simply remove each word as it's called out, until the array gets to be zero entries long.
NSMutableArray* scoreArrayCopy = [NSMutableArray arrayWithArray:scoreArray];
int originalCount = scoreArrayCopy.count;
...
while (scoreArrayCopy.count > 0) {
NSString* guess = <get next guess>;
[scoreArrayCopy removeObject:guess];
score = originalCount - scoreArrayCopy.count;
}
(If you have a lot of words things would be more efficient if you used an NSMutableSet instead of an NSMutableArray, but the logic would be the same.)

Obj-C - NSString that saves all input using currentTitle and UILabel.text methods

NSString* digit = [sender currentTitle];
if (self.userIsInTheMiddleOfEnteringANumber){
NSString* currentDisplayText = [[self display]text];
NSString* newDisplayText = [currentDisplayText stringByAppendingString:digit];
self.display.text = newDisplayText;
I´ll try and explain my problem as good as I can. This line of code here takes the digit from a selection of buttons, saves it no the string "digit". "currentDisplayText"takes the digit displayed in a label. Then these two strings are appended and sent to the "display" (label)
But there is also an enter button. Which clears the display (so user can enter new number ) this is a calculator btw!
- (IBAction)enterPressed{
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
What I want is to display a "history" label that displays all the numbers entered - I have not quite understood how I get the string I save the "history" too, to not reset like the display does. This might be bad exlained by me, but any hints are appreciated. I am still learning objective-c...
If I understood you correctly, you want to save the number after pressing the enter button. For this you need to add an attribute of type NSMutableArray to your class. Then in the method do:
- (IBAction)enterPressed {
[myHistoryArrayAttrib addObject: self.display.text];
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
//after this you can clear your display
self.display.text = nil;
}
That's it.
I did not understander you very well , but one thing I am sure , if you want save your data (not very large) , you should use NSUserDeafult . use - (void)setObject:(id)anObject forKey:(id)aKey;to save the data.
You want to svae the history , if you want to save the lastest history , you could use - (NSString *)stringForKey:(NSString *)defaultName; to get the string which you save. and if you want to save the whole history , you could use - (NSArray *)arrayForKey:(NSString *)defaultName; to get the array which you save.
give an eg. how to save a string
if([[NSUserDefaults standardUserDefaults] stringForKey:theKey] == nil)
{
NSString *defaultValue = [NSString stringWithString:theStringYouWantedSave];
NSDictionary *saveDict = [NSDictionary dictionaryWithObject:defaultValue forKey:theKey];
[[NSUserDefaults standardUserDefaults] registerDefaults:saveDict];
}
else
{
[[NSUserDefaults standardUserDefaults] setObject:theStringYouWantedSave forKey:theKey];
}
and get like this
if([[NSUserDefaults standardUserDefaults] stringForKey:theKey]!=nil)
{
yourHistoryString = [[NSUserDefaults standardUserDefaults] stringForKey:theKey];
}

Objective C : Writing into a Plist

Even though i know there are at least 2 or 3 topics with this name, i didnt find a proper answer so far to my problem :
I want to edit a Plist (which has been created by zwoptex (image/animations program)) in order to divide every number in it by 2.
So in my plist i do have some keys like "spriteOffset" with {{182, 160}, {58,75}} or {192, 165} as value. Those are NSStrings, and i just want to modify the numbers so i need to check if there's a "{" or a space or such, then casting the number.
The thing is i don't really know how to do it.....
Also, it seems that i'm missing something with my plist management. I've put some NSLogs for displaying every of those strings in my plist, but.... nothing gets displayed...
So here is my code :
-(void)DivideValues
{
for(NSString * plistName in plistSubpathsByName)
{
NSMutableDictionary* infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:#"%#.plist",plistName]];
for(NSDictionary * sprite in [infoDict objectForKey:#"frames"])
{
for(NSString * string in [infoDict objectForKey:#"spriteColorRect"])
{
NSLog(#"%#",string);
}
for(NSString * string in [infoDict objectForKey:#"spriteOffset"])
{
NSLog(#"%#",string);
}
for(NSString * string in [infoDict objectForKey:#"spriteSize"])
{
NSLog(#"%#",string);
}
for(NSString * string in [infoDict objectForKey:#"spriteSourceSize"])
{
NSLog(#"%#",string);
}
for(NSString * string in [infoDict objectForKey:#"textureRect"])
{
NSLog(#"%#",string);
}
}
}
}
Thanks for any response, and i wish you all good luck for your career/passion
First of all, you should replace [infoDict objectForKey:#"spriteColorRect"] with [sprite objectForKey:#"spriteColorRect"], since the sprite is probably the dict containing further information.
You don't see any logs because -objectForKey: returns nil for a key that does not exist.
For changing the values, you might try to create a CGPoint or CGRect from the string, then changing it and finally converting it back to a string. (CGPointFromNSString() and NSStringFromCGPoint)
To save the modified version of your dictionary use NSDictionary's -writeToFile:atomically:.
The reason you example logs nothing is most likely because your inner for..in loops are probably looking in the wrong dictionary: the outer loop gets a dictionary sprite, so shouldn't the inner loops be looking at keys in that dictionary?
If you want to read a property list in, change some values in it, and write the same property list back out, you might find it useful to look at the NSPropertyListSerialization class -- it lets you quickly get a structure of mutable arrays/dictionaries from plist data, so you can iterate into them however you'd like to change values within, then serialize the whole thing back to data again. (If you use dictionaryWithContentsOfFile: you'll get a mutable dictionary, but all the containers within it will be immutable, so you'd have to do mutableCopy and swizzle contents all over the place during your iteration.)
No time to write up more detail at the moment, but I might edit the answer later if looking up the docs for NSPropertyListSerialization doesn't help you.
Ok I did succeed so if anyone is interested here is the code :
-(void)DivideValues
{
for(NSString * xflName in [xflSubpathsByName objectEnumerator]){
NSMutableDictionary* infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:[sourceFolder stringByAppendingPathComponent:xflName]];
NSDictionary * dictionary = [infoDict objectForKey:#"frames"];
NSMutableDictionary * mutabledictionary = [[dictionary mutableCopy] autorelease];
for(NSString * pngFileName in dictionary) {
NSDictionary * sprite = [dictionary objectForKey:pngFileName];
NSLog(pngFileName);
NSMutableDictionary * mutablesprite = [[sprite mutableCopy] autorelease];
NSString * newstring = [self castSpriteRect:[sprite objectForKey:#"spriteColorRect"]];
[mutablesprite setObject:newstring forKey:#"spriteColorRect"];
newstring = [self castSprite:[sprite objectForKey:#"spriteOffset"]];
[mutablesprite setObject:newstring forKey:#"spriteOffset"];
newstring = [self castSprite:[sprite objectForKey:#"spriteSize"]];
[mutablesprite setObject:newstring forKey:#"spriteSize"];
newstring = [self castSprite:[sprite objectForKey:#"spriteSourceSize"]];
[mutablesprite setObject:newstring forKey:#"spriteSourceSize"];
newstring = [self castSpriteRect:[sprite objectForKey:#"textureRect"]];
[mutablesprite setObject:newstring forKey:#"textureRect"];
[mutabledictionary setObject:mutablesprite forKey:pngFileName];
}
[infoDict setObject:mutabledictionary forKey:#"frames"];
[infoDict writeToFile:[sourceFolder stringByAppendingPathComponent:xflName] atomically:NO];
}
if(!cancelling)
++digestStage;
else
digestStage = End;
}
-(NSString *)castSprite:(id)obj{
CGPoint point = NSPointFromString((NSString *)obj);
int i = (int)point.x%2 == 0 ?(int)point.x/2:1+(int)point.x/2;
int j = (int)point.y%2 == 0 ?(int)point.y/2:1+(int)point.y/2;
NSString * res = [NSString stringWithFormat:#"{%d, %d}",i,j];
return res;
}
-(NSString *)castSpriteRect:(id)obj{
CGRect point = NSRectFromString((NSString *)obj);
int i = (int)point.origin.x%2 == 0 ?(int)point.origin.x/2:1+(int)point.origin.x/2;
int j = (int)point.origin.y%2 == 0 ?(int)point.origin.y/2:1+(int)point.origin.y/2;
int y = (int)point.size.width%2 == 0 ?(int)point.size.width/2:1+(int)point.size.width/2;
int x = (int)point.size.height%2 == 0 ?(int)point.size.height/2:1+(int)point.size.height/2;
NSString * res = [NSString stringWithFormat:#"{{%d, %d}, {%d, %d}}",i,j,y,x];
return res;
}

Using a String representing the name of a variable to set the variable

This is a basic example that I know can be simplified, but for testing sake, I would like to do this in such a way. I want to set a variable based on an appending string (the variables "cam0" and "pos1" are already declared in the class). The appending string would essentially be an index, and i would iterate through a loop to assign cameras (cam0, cam1..) to different positions (pos0, pos1..).
cam0 is defined as an UIImageView
pos1 is defined as a CGRect
This works for a NSString Variable named coverIndex:
NSString* text = [[NSString alloc] initWithString:#""];
NSLog(#"%#",(NSString *)[self performSelector:NSSelectorFromString([text stringByAppendingString:#"coverIndex"])]);
The correct string that I set for coverIndex was logged to the Console.
Now back to my UIImageView and CGRect. I want this to work.
NSString* camText = [[NSString alloc] initWithString:#"cam"];
NSString* posText = [[NSString alloc] initWithString:#"pos"];
[(UIImageView *)[self performSelector:NSSelectorFromString([camText stringByAppendingString:#"0"])] setFrame:(CGRect)[self performSelector:NSSelectorFromString([posText stringByAppendingString:#"1"])]];
My error is "Conversion to non-scalar type requested"
This is the only way I found to do this sort of thing (and get the NSLog to work), but I still believe there is an easier way.
Thank you so much for any help :)
Use KVC, it's an amazing piece of technology that will do just what you want:
for (int index = 0; index < LIMIT; index++) {
NSString *posName = [NSString stringWithFormat:#"pos%d", index];
CGRect pos = [[self valueForKey:posName] CGRectValue];
NSString *camName = [NSString stringWithFormat:#"cam%d", index];
UIImageView *cam = [self valueForKey:camName];
cam.frame = pos;
}
One way you can do this would be to create your cameras in a dictionary and use those special NSStrings to key in to it. Like,
NSMutableDictionary *myCams;
myCams = [[myCams alloc] init];
[myCams addObject:YOUR_CAM0_OBJECT_HERE forKey:#"cam[0]"];
[myCams addObject:YOUR_CAM1_OBJECT_HERE forKey:#"cam[1]"];
NSString camString = #"cam[0]"; // you'd build your string here like you do now
id theCamYouWant = [myCams objectForKey:camString];