How to sort plist by its value - iphone

I have Plist with list with List of Dictionaries(item0,item1,item2).and I populate this plist in the Graph..its works fine.and in Plist key (date)-> Value(i store by using NSDate) .Now I need to sort the Plist in such a way that:-
graph should display for only one week.
say if first value is 26-Dec-12 than only upto 1-Jan-13(1 week) values plist should display
.
code :
- (NSArray *)readFromPlist
{
// get paths from root direcory
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"calori.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:documentPlistPath];
valueArray = [dict objectForKey:#"title"];
return valueArray;
}
and
- (void)drawRect:(CGRect)rect {
// Drawing code
CGContextRef _context = UIGraphicsGetCurrentContext();
ECGraph *graph = [[ECGraph alloc] initWithFrame:CGRectMake(10,10, 480, 320)
withContext:_context isPortrait:NO];
NSMutableArray *Array=[NSMutableArray arrayWithArray:[self readFromPlist]];
NSMutableArray *items = [[NSMutableArray alloc] init];
for (id object in [Array reverseObjectEnumerator]){
if ([object isKindOfClass:[NSDictionary class]])
{
NSDictionary *objDict = (NSDictionary *)object;
tempItemi =[[ECGraphItem alloc]init];
NSString *str=[objDict objectForKey:#"title"];
NSLog(#"str value%#",str);
float f=[str floatValue];
NSString*str1=[objDict objectForKey:#"date"];
NSLog(#" str values2-- %#",str1);
tempItemi.isPercentage=YES;
tempItemi.yValue=f;
tempItemi.name=str1;
[items addObject: tempItemi];
}
}
[graph drawHistogramWithItems:items lineWidth:2 color:[UIColor blackColor]];
}

As your requirement is to filter date within 7 days,
I am giving you a logic, try this way:
- (NSArray *)readFromPlistForOneWeek {
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"calori.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:documentPlistPath];
//loop through each of the item
//and check if <8 then add that keyValue to array
NSMutableArray *tempValueArray=[NSMutableArray new];
for (NSDictionary *subDict in [dict objectForKey:#"title"]) {
// NSLog(#"=> %#",subDict);
NSString *plistDateString=[subDict objectForKey:#"date"];
NSDate *currentDate = [NSDate date];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"dd-MMM-yy"];
NSDate *plistDate=[dateFormatter dateFromString:plistDateString];
NSString *currentDateString=[dateFormatter stringFromDate:currentDate];
NSTimeInterval secondsBetween = [plistDate timeIntervalSinceDate:currentDate];
NSInteger dateDiff = secondsBetween / 86400;
if( dateDiff<8 ){ //within 0-7 days
[tempValueArray addObject:subDict];
}
}
NSLog(#"valuArray : %#",tempValueArray);
return tempValueArray;
}

Have you tried with NSSortDescriptor?
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"DATE" ascending:YES selector:#selector(compare:)];
[yourDictionary sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];

Try this
NSString *path = [[NSBundle mainBundle] pathForResource:#"yourfile" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
// sort it
NSArray *sortedArray = [[myDict allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
// iterate and print results
for(NSString *key in sortedArray) {
NSLog(#"key=%#,value=%#", key, [dict objectForKey:key]);
}

Related

Searching for objects in array by name

is there a possibility to check for an object in an array by name.
At some point in my app I need to access the plist and pull information stored under an object which I found by its name.
The reason I need to do this is because I don't have the integer number under which where the object is placed in my array.
I have started the usual procedure but i'm not getting anywhere. Maybe its just getting a little too late for me....
This is how my plist looks
Array
Dictionary
title ...
text ...
ect ...
Dictionary
title ...
text ...
ect ...
Dictionary
title ...
text ...
ect ...
My code so far isn't helping at all. I'm definitely doing something wrong.
-(NSString*)nameFromPlist:(NSString*)name {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"Orte.plist"];
_regionArray = [NSArray arrayWithContentsOfFile:writableDBPath];
NSString *string = [[NSString alloc]init];
for(NSDictionary *dict in _regionArray) {
string = [[dict objectForKey:name] valueForKey:#"title"];
}
return [NSString stringWithFormat:#"%#",string];
}
My string is just returning null.
Any ideas anyone?
Thanks a lot!
ANSWER:
Here is the code for everyone:
-(NSString*)nameFromPlist:(NSString*)name {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *tmpFileName = [[NSString alloc] initWithFormat:#"Orte.plist"];
NSString *path = [documentsDirectory stringByAppendingPathComponent:tmpFileName];
NSString *string;
NSMutableArray *array = [NSMutableArray arrayWithContentsOfFile:path];
NSDictionary *dict = [[NSDictionary alloc] init];
NSString *title;
for (int i=0; i<[array count]; i++) {
dict = [array objectAtIndex:i];
title = [dict valueForKey:#"title"];
if([title isEqualToString:name]) {
string = [dict valueForKey:#"title"];
NSLog(#"Titel: %#", string);
}
}
return [NSString stringWithFormat:#"%#",string];
}
Thank a lot everyone!
First you don't need to alloc the NSString, 'cause you'll get a different one from valueForKey.
Then if I understood right what you want to get a better code may be something that make use of NSPredicate or the block-based indexOfObjectPassingTest. Both iterate across the array and perform a test on the elements to get you the matching elements (or the index of them).
NSString* plistPath = [[NSBundle bundleForClass:[self class]] pathForResource:#"<PlistFileName>" ofType:#"plist"];
NSArray *array = [[NSArray alloc] initWithContentsOfFile:plistPath];
NSMutableArray* titles = [[NSMutableArray alloc] init];
for (NSDictionary* d in array)
[titles addObject:[d objectForKey:#"title"]];
NSLog(#"Object found at index %i", [a indexOfObject:#"<Your object name>"]);
Make sure you're testing against NSNotFound for failure to locate, and not (say) 0.

Simple NSSArray regarding strings and NSRangeException

I have a simple question. I am designing some simple highscores code yet I am having alot of trouble with it, specifically storing and saving players names. I have not been programming for very long in obj-c, only 2 weeks. I am not quite sure what is going on when I use NSStrings in an array.
Here is the code for saving strings:
-(NSString *) getFilePath2 {
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:#"savedFile2.plist"];
}
-(void) savePlayerNameData {
NSArray *highScoreNames = [[NSArray alloc]
initWithObjects:
playerName1,
playerName2,
playerName3,
playerName4,
playerName5,
nil];
[highScoreNames writeToFile:[self getFilePath2] atomically:YES];
}
-(void) loadPlayerNameData{
// load data here
NSString *myPath = [self getFilePath2];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if (fileExists) {
NSArray *values = [[NSArray alloc] initWithContentsOfFile:myPath];
playerName1 = [values objectAtIndex:0];
playerName2 = [values objectAtIndex:1];
playerName3 = [values objectAtIndex:2];
playerName4 = [values objectAtIndex:3];
playerName5 = [values objectAtIndex:4];
}
else {
NSLog(#"first Launch. no file yet");
}
}
I end up getting this error :
2012-08-15 22:25:30.780 Pig Fly![5304:f803] *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
*** First throw call stack:
(0x14c5022 0xec5cd6 0x146da48 0x146d9b9 0x14bec30 0xbd21 0x62e2 0x964eb6 0x1499936 0x14993d7 0x13fc790 0x13fbd84 0x13fbc9b 0x13ae7d8 0x13ae88a 0x28626 0x1fdd 0x1f45)
terminate called throwing an exception(lldb)
However, what I find very interesting is that when I write similar code for saving int values, The program runs fine. This is the working int code:
-(NSString *) getFilePath {
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:#"savedFile.plist"];
}
-(void) saveData {
//save data here
NSArray *highScores = [[NSArray alloc]
initWithObjects:
[NSString stringWithFormat:#"%i",highScore1],
[NSString stringWithFormat:#"%i",highScore2],
[NSString stringWithFormat:#"%i",highScore3],
[NSString stringWithFormat:#"%i",highScore4],
[NSString stringWithFormat:#"%i",highScore5],
nil];
[highScores writeToFile:[self getFilePath] atomically:YES];
}
-(void) loadData{
// load data here
NSString *myPath = [self getFilePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if (fileExists) {
NSArray *values = [[NSArray alloc] initWithContentsOfFile:myPath];
highScore1 = [[values objectAtIndex:0] intValue];
highScore2 = [[values objectAtIndex:1] intValue];
highScore3 = [[values objectAtIndex:2] intValue];
highScore4 = [[values objectAtIndex:3] intValue];
highScore5 = [[values objectAtIndex:4] intValue];
}
else {
NSLog(#"first Launch. no file yet");
}
}
Can anybody tell me what is going on? What are the differences that need to be kept in mind when writing NSArrays for ints and NSStrings?
Make sure that playerName1 is not NULL.

read and write using NSKeyedArchiver, ios

Below is a class to read and write data using nsarchive
Data.m
-(id)init {
self = [super init];
if(self) {
arr = [[NSMutableArray alloc] init];
}
return self;
}
-(NSString *)getPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath;
if ([paths count] > 0)
documentPath = [paths objectAtIndex:0];
NSString *draftDataPath = [documentPath stringByAppendingPathComponent:#"draftData.dat"];
return draftDataPath;
}
-(void)saveDataToDisk {
NSString *path = [self getPath];
[NSKeyedArchiver archiveRootObject:arr toFile:path];
}
-(void)loadDataFromDisk {
NSString *path = [self getPath];
self.arr = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
}
At later on, I am adding some objects into arr by doing
CustomerClass.m
- (void) viewDidLoad {
Data *data = [[Data alloc] init];
[data.arr addObject:myObject1]
[data.arr addObject:myObject2]
[data.arr addObject:myObject3]
[data saveDataToDisk];
}
At DisplayData.m, I want to check data.arr by
- (void) viewDidLoad {
Data *data = [[Data alloc] init];
[data loadDataFromDisk];
NSLog(#"length of array is %d",[data.arr count]);
}
On the console, I am getting
length of array is 1
I thought it should be 3 after all.
Please point out what I have just made a mistake in the middle of work if you have any clues about it.
So, I suspect that your "myObjects" are not NSCoding compliant. I just did this:
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:3];
[arr addObject:#"Hello"];
[arr addObject:#" "];
[arr addObject:#"World"];
BOOL ret = [NSKeyedArchiver archiveRootObject:arr toFile:[self getPath]];
NSArray *arr2 = [NSKeyedUnarchiver unarchiveObjectWithFile:[self getPath]];
NSLog(#"count = %d", [arr2 count]);
And the results was "count = 3"
I feel like there's too much code here to do what you're looking for. I think all you need is:
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:dataClass] forKey:NSUserDefaultString];
[[NSUserDefaults standardUserDefaults] synchronize];
to save it.
And:
NSData *someData = [[NSUserDefaults standardUserDefaults] objectForKey:NSUserDefaultString];
if (settingsData != nil)
{
dataClass = [NSKeyedUnarchiver unarchiveObjectWithData:settingsData];
}
to retrieve it.

NSDictionary within NSArray

A quick question about NSArrays and NDictionarys.
I have and NSArray containing NSDictionarys.
The NSDictionary contain a date and a string.
What I would like to do is end up with an NSDictionary with keys dates and values arrays of strings that are on that date.
What would be the best way to do this
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (NSDictionary *dict in array) {
NSDate *date = [dict objectForKey:#"dateKey"];
NSString *string = [dict objectForKey:#"stringKey"];
NSMutableArray *stringsWithDate = [result objectForKey:date];
if (!stringsWithDate) {
stringsWithDate = [NSMutableArray array];
[result setObject:stringsWithDate forKey:date];
}
[stringsWithDate addObject:string];
}
Note that NSDate is not a "calendar date", so the same day with a different time will be considered as a distinct date in your result dictionary.
As I do not see any reasonable motivation for doing this, let's call it code golf.
NSMutableArray *dates = [NSMutableArray array];
NSMutableArray *strings = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
[dates addObject:[dict objectForKey:#"date"]];
[strings addObject:[dict objectForKey:#"string"]];
}
NSArray *datesArray = [[NSArray alloc] initWithArray:dates];
NSArray *stringsArray = [[NSArray alloc] initWithArray:strings];

how to write plist array of dictionary objects..dynamically and populating the tableview

m working with plist and i am new to it..
I want to save two type of values,these two are labels,i.e
label1
label2
so for that i tried to write the code but was able to save only for one
label i.e label1..in a plist and then populate it into the table so i got one value on
cell.textlabel.text = label1.text
but i need this also..
cell.detailedlabel.text = label2.text
so below is my code.. to save label1.text
-(IBAction) myBrand:(id) sender
{
NSLog(#"mylist Clicked");
NSMutableArray *array = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [docsDir stringByAppendingPathComponent:#"Data.plist"];
[array addObjectsFromArray:[NSArray arrayWithContentsOfFile:plistPath]];
[array addObject:searchLabel.text];
[array writeToFile:plistPath atomically: TRUE];
}
now if i want o save one more label..in the array and populate it on cells detailedlabel..how shall i proceed..please help me out..
Hi friends..I want o have something like this....
NSMutableArray *array = [[NSMutableArray alloc] init];
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0]; // get the path to our Data/plist file
NSString *plistPath = [docsDir stringByAppendingPathComponent:#"Data.plist"];
//This copies objects of plist to array if there is one
[array addObjectsFromArray:[NSArray arrayWithContentsOfFile:plistPath]];
//[array addObject:entity];
[array insertObject:entity atIndex:0];
[array insertObject:category atIndex:0];
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: entity, category, nil] forKeys:[NSArray arrayWithObjects: #"Entity", #"Category", nil]];
Regards
Ranjit
go through the portion of the code below which will solve your problem of storing both label values in plist...
NSMutableArray *data = [[NSMutableArray alloc] init];
NSMutableDictionary* newDict = [[NSMutableDictionary alloc] init];
[newDict setValue:label1.text forKey:labell]; //forKey identify the name of the array element in dictionary for plist
[newDict setValue:label2.text forKey:label2];
[data addObject:newDrink];
[newDict release];