NSDictionary only returns one entry - objective-c

I am trying to access all of my NSDictionary values after call a method that sets my dictionary items. For some reason after I invoke the method and try to log out all of my items, it only returns one item and it's also the last item in the dictionary.
Here's where I set the dictionary:
-(void)setDestinationDictionary {
destinationFileDict = [[NSMutableDictionary alloc] init];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *DestinationFiles = [fileManager contentsOfDirectoryAtPath:destinationPath error:nil];
for (NSString *file in DestinationFiles) {
NSString *sourceFile = [[destinationPath stringByAppendingPathComponent:file] lastPathComponent];
NSImage *image = [NSImage imageNamed:sourceFile];
CGFloat imageWidth = [image size].width;
CGFloat imageHeight = [image size].height;
[destinationFileDict setObject:sourceFile forKey:#"fileName"];
[destinationFileDict setObject:[NSNumber numberWithFloat:imageWidth] forKey:#"imageWidth"];
[destinationFileDict setObject:[NSNumber numberWithFloat:imageHeight] forKey:#"imageHeight"];
}
Here's where I try to call the method and log the contents of the dictionary:
-(void)initiateCopy {
[self setDestinationDictionary];
NSLog(#"%#", destinationFileDict);
}
There should be a total of 18 entries in the dictionary, but I'm only returning one and it's the last record.

Your dictionary contains three keys: fileName, imageWidth, and imageHeight.
In setDestinationDictionary, on each pass through the for loop, you set the same three keys in the same dictionary. Each pass replaces the values you stored on the prior pass. Thus at the end of setDestinationDictionary, the dictionary still contains only three keys, and the values are the values set in the last pass through the loop.
Perhaps you want to create an array of dictionaries, one for each destination file. Or perhaps you want to use the filename as the key and store the size as the value (in which case, look at +[NSValue valueWithSize:] and -[NSValue sizeValue]).

Related

Reading float from a custom file

I want to read some float value one by one from a custom file I defined "player.geo".
player.geo is a file I created using Xcode 4 ("Empty File" from the File > New menu)
I'm currently trying to do it like this:
- (id) initWithGeometryFile:(NSString *) nameOfFile
{
NSFileHandle *geoFile = NULL;
NSString *geoFilePath = [[NSBundle mainBundle] pathForResource:#"player" ofType:#"geo"];
geoFile = [NSFileHandle fileHandleForReadingAtPath:geoFilePath];
if(geoFile == NULL)
{
NSLog(#"Failed to open file.");
}
else
{
NSLog(#"Opening %# successful", nameOfFile);
NSMutableData *fileData = [[NSMutableData alloc] initWithData:[geoFile readDataOfLength:4]];
float firstValue;
[fileData getBytes:&firstValue length:sizeof(float)];
NSLog(#"First value in file %# is %f", nameOfFile, firstValue);
}
return self;
}
I'm not getting the expected value of -64.0, rather I'm getting 0.0.
Is this the right way to go about it?
Do I really have to read the file as a string and then parse float the string contents to get the float value?
NSData objects deal with raw bytes, not strings. If you are typing in a string into a txt file, this will not work. If you are using NSData objects, then you will need to first write the data using the data object methods such as writeToFile:atomically:.
Alternately, you can use the NSString functions stringWithContentsOfFile and componentsSeperatedByString to generate an NSArray containing each string on it's own line, like so:
NSString *tmp;
NSArray *lines;
lines = [[NSString stringWithContentsOfFile:#"testFileReadLines.txt"]
componentsSeparatedByString:#"\n"];
NSEnumerator *nse = [lines objectEnumerator];
while(tmp = [nse nextObject]) {
NSLog(#"%#", tmp);
}

Null output troubles

Okay I've been trying at this for about 2-3 hours now and I don't seem to quite get it. Here is the code and a brief explanation:
I'm trying to make two lists of words, pull one word from each of those lists at random, and display both words (along with a third) on the screen when a button is pressed. Here is the code:
#import "Project001ViewController.h"
#implementation Project001ViewController
-(ArrayOfWords *) advs
{
if(!advs){
advs = [[ArrayOfWords alloc] init];
NSString* advpath = #"/WordLists/adverbs.txt";
NSLog(#"1");
[[self advs] populateListOfWords:advpath];
}
return advs;
}
-(ArrayOfWords *) adjs
{
if (!adjs) {
adjs = [[ArrayOfWords alloc] init];
NSString* adjpath = #"/WordLists/adjectives.txt";
[[self adjs] populateListOfWords:adjpath];
NSLog(#"2");
}
return adjs;
}
- (IBAction)generate:(UIButton *)sender;
{
//int randy = arc4random() % 11;
//NSNumber* num= [NSNumber numberWithInteger:randy];
NSString* obj = #"app";
NSString* adverb = [[self advs] randomItem];
NSString* adjective = [[self adjs] randomItem];
NSLog(#"%i %i",[adjs size],[advs size]);
NSLog(#"1 %# %# %#.",adverb, adjective, obj);
//NSLog(#"%#",thePhrase);
[display setText:#"Hi"];
}
#end
I'm having trouble on the last NSLog line:
NSString* obj = #"app";
NSString* adverb = [[self advs] randomItem];
NSString* adjective = [[self adjs] randomItem];
NSLog(#"%i %i",[adjs size],[advs size]);
NSLog(#"1 %# %# %#.",adverb, adjective, obj);
Instead of getting the two randomly selected words (using arc4random() to produce them) the array returns Null. But I know FOR CERTAIN. That the array's are not empty because the NSLog Line where I print [adjs size] and [advs size] I get the correct sizes of the list of words. I just want to know what is causing them to print Null here.
populateListOfWords, randomItem, and size methods:
- (NSArray *) populateListOfWords:(NSString *) path {
//gets the components of the file into an NSString
NSString *wordListString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
//returns an array of all the words (uses the next line indicator '\n' to know when it's at the end of the word
NSArray* words = [wordListString componentsSeparatedByString:#"\n"];
length=(NSNumber*)([words count]);
return words;
}
-(NSString*) randomItem{
//returns random object in list
return (NSString*)[list objectAtIndex:(arc4random() % (int)length)] ;
}
-(int) size{
//returns size of list
return (int)length;
}
(If more code is needed let me know and thank you in advanced for any and all help).
I believe there is a problem with the paths. It is impossible to have access to the path /WordLists/adjectives.txt in iOS due to the application sandbox. I suggest you add these files to the application by dragging and dropping them onto the project. You can get the file paths for resources in application bundle using
NSString * path = [[NSBundle mainBundle] pathForResource:#"adjectives" ofType:#"txt"];
Now pass this path to the method populateListOfWords:.
Because of the incorrect path, I believe wordListString is nil and everything else follows to be that.
Another thing is that int and NSNumber are not toll free bridged like NSStrings and other foundation objects. So
length=(NSNumber*)([words count]);
is incorrect. I suggest you define length as int or better NSUInteger to match the type count method returns.
This method is the problem:
- (NSArray *) populateListOfWords:(NSString *) path {
//gets the components of the file into an NSString
NSString *wordListString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
//returns an array of all the words (uses the next line indicator '\n' to know when it's at the end of the word
NSArray* words = [wordListString componentsSeparatedByString:#"\n"];
length=(NSNumber*)([words count]);
return words;
}
It wasn't actually putting the words in a list that anyone else could access. I had to just modify it like so:
- (void) populateListOfWords:(NSString *) path {
//gets the components of the file into an NSString
NSString *wordListString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
//returns an array of all the words (uses the next line indicator '\n' to know when it's at the end of the word
NSArray* words = [wordListString componentsSeparatedByString:#"\n"];
list = words;
length=(int)([words count]);
}
Now it gives me the correct output. But for some reason when I press the button twice it crashes. Oh well that's a new problem. Thanks again for all the help.
UPDATE
Turns out advs and adjs were being released so the second go around it was trying to access a nil value because when I call [self advs] [self adjs] the pointers exist, but their contents do not. I had to go back and refill them each time basically removing the if (!advs) and if (adjs) parts. It now works as intended.

Image on TableView which is retrieved from CoreData

I want to display an image that is being retrieved from core data and every single cell will have a different image. I have done this but I do not know how to retrieve from this path and place the image into the cell. Anybody can help me on this? Thanks in advance.
NSString * filePath = #"01.jpg";
NSData * imageData = UIImageJPEGRepresentation([UIImage imageNamed:filePath], 0.1);
[productInfo setValue:imageData forKey:#"productImage"];
You could fetch the managed object from your model and place it in the array where the array would contain the photo names as below. I am assuming that your entity be photoStore and the column for storing the photo file name be nameOfPhoto, so the code would look like,
NSFetchRequest *fetchRequest=[[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity=[NSEntityDesription entityForName:#"photoStore" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity : entity];
NSArray fecthedObject = [fetchRequest executeFetchRequest:fetchRequest error:nil];
for(NSManagedOect *photos in fetchedObect)
{
[self.arrayOfImageNames addObject : [photos valueForKey :#nameOfPhoto"]];
}
Now, inside the cellForRowAtIndexPath use the image name to add the image to your cell's imageview as,
NSString *imagePath = [NSHomeDirectory() stringByAppendingString : [[self.arrayOfImageNames objectAtIndex:indexpath.row] stringByAppendingPathComponent:"jpg"]];
cell.imageView.image=[UIImage imageNamed:imagePath];
This is how you would add the store the image name into core data and then retrieve the name construct a path to it and display it.
if you want to get path use this -
[[NSBundle mainBundle] pathForResource:#"01" ofType:#"jpg"];

UISlider core data programing

Im working on a simple "point based" app.
under settings the user set´s the number of points needed to get a "goodie" using a slider.
-(IBAction) sliderChanged: (id)sender {
UISlider *slider = (UISlider *) sender;
int progressAsInt =(int)(slider.value +0.5);
NSString *newText = [[NSString alloc] initWithFormat:#"%d",progressAsInt];
sliderLabel.text = newText;
[newText release];
this works fine, but how so i store the slider value in my core data model, and how do make my slider show the stored value when view loads.
hope u can help me out :-D
Hey gerry3 i found my error. i never set my toD-object in my settingsViewController, with:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription
entityForName:#"ToDo" inManagedObjectContext:_context]];
NSError *error = nil;
NSArray *array = [_context executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
if(array.count > 0){
toDo = [array objectAtIndex:0];
} else { // no one to fetch - generate one
toDo = [NSEntityDescription
insertNewObjectForEntityForName:#"ToDo"
inManagedObjectContext:_context];
[toDo retain];
your code works like a charm .....
Thanks
Skov
The key here is that Core Data stores numeric attributes (e.g. integers, floats, etc) as NSNumber objects.
Say that your entity is called Record and it has a integer attribute called 'progress'.
If you create a managed object instance of Record named 'record', then you can set its progress like this:
[record setValue:[NSNumber numberWithInteger:progressAsInt] forKey:#"progress"];
When you want to update your view with the value from your model (usually in viewWillAppear:), you can get its progress like this:
NSNumber *progressNumber = [record valueForKey:#"progress"];
slider.value = [progressNumber floatValue];
Alternatively, if you generate the class files for the Record entity, you can just do:
record.progress = [NSNumber numberWithInteger:progressAsInt];
and:
slider.value = [record.progress floatValue];

How can Add new line in plist

Hi friends i'm beginner
and sorry for simple Questions.
how can i add new lines in ""plist"" for saving data
and access keys in it.
NSArray *values = [[NSArray alloc] initWithObjects:#"Hello",nil];
[values writeToFile:[self PathArray] atomically:YES];
because , this method Only overwrite Values in ([self PathArray]) "path";
Thanks
Plist files are not designed for incremental updates, instead you should load plist contents in memory, add an item to it and save back:
NSMutableArray *oldValues = [NSMutableArray arrayWithContentsOfFile:[self PathArray]];
NSArray *values = [[NSArray alloc] initWithObjects:#"Hello",nil];
[oldValues addObjectsFromArray:values];
[oldValues writeToFile:[self PathArray] atomically:YES];
[values release]; // Do not forget this line to avoid memory leak
In my item, the dictionary data includes null, for example :
{
"category_id" = 29;
"category_name" = "\U5f69\U6f2b";
coverurl = "<null>";
position = 29;
}
so writetofile, return value always FALSE.