How to fetch data from pList in Label - iphone

I have a RegistrationController screen to store email-id ,password,DOB,Height,Weight and logininController screen to match email-id and password to log-in purpose.
Now, In some third screen I have to fetch only the Height,Weight from the plist of the logged-in user to display it on the label.now if I Store the values of email-id and password in from LoginViewController in string and call it in the new screen to match if matches then gives Height,Weight ..if it corrects then how to fetch Height,Weight from the plist of the same one.
How can I fetch from the stored plist in a string?
Here is my code:
-(NSArray*)readFromPlist
{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"XYZ.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:documentPlistPath];
NSArray *valueArray = [dict objectForKey:#"title"];
return valueArray;
}
- (void)authenticateCredentials {
NSMutableArray *plistArray = [NSMutableArray arrayWithArray:[self readFromPlist]];
for (int i = 0; i< [plistArray count]; i++)
{
id object = [plistArray objectAtIndex:i];
if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *objDict = (NSDictionary *)object;
if ([[objDict objectForKey:#"pass"] isEqualToString:emailTextFeild.text] && [[objDict objectForKey:#"title"] isEqualToString:passwordTextFeild.text])
{
NSLog(#"Correct credentials");
return;
}
NSLog(#"INCorrect credentials");
} else {
NSLog(#"Error! Not a dictionary");
}
}
}

First get whole value from your plist file after that store this NSArray into NSMutableArray and get the value with its objectAtIndex and valueForKey property..see whole example bellow..
UPDATE :
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"yourFileName" ofType:#"plist"];
NSArray *contentArray = [NSArray arrayWithContentsOfFile:plistPath];
NSMutableArray *yourArray = [[NSMutableArray alloc] initWithArray:contentArray];
for (int i = 0; i< [yourArray count]; i++)
{
id object = [yourArray objectAtIndex:i];
if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *objDict = (NSDictionary *)object;
yourLableWeight.text = [[objDict objectForKey:#"Weight"];// set index with your requirement
yourLableHeight.text = [[objDict objectForKey:#"Height"];
}
hope this help you...

When you enter credentials on login screen to check when it match the credentials with the fetched plist then pass that plist to the next controller. Do something like this
UserViewController *controller = [[UserViewController alloc] initWithNibName:#"UserViewController" bundel:nil];
[controller setUserDictionary:yourPlistDictionary];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
in UserViewController you would have a NSDictionary instance to store the data to show, hope that will help you

Related

Implementing a Search History feature in iOS

I've got a search page at the moment which will load a list of results for a web-service, but when I return to the search page I would like to 'save' whatever was entered (e.g. 'resto italian') and then display that entry and previous entries into a table view below, like in my following image:
My plan was to use property list serialization - if there isn't already a list, create a property list called history.plist, and populate it with each search term that is made, and display the nearest ten in the table view like above.
What I've tried:
// should create history.plist
- (NSString *)dataFilePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingString:#"history.plist"];
}
/* This is the action for when 'search' is clicked - calls the method above to create
a new plist if it's not already created.
I then try to display the contents of the of the file in the textfield itself
(for testing purposes) but it's not saving/displaying properly at the moment. */
- (IBAction)saveHistory:(id)sender {
NSString *filePath = [self dataFilePath];
if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
for (int i = 0; i < (sizeof(array)); i++) {
UITextField *theField = self.searchHistory;
theField.text = [NSString stringWithFormat:#"%#", array];
}
}
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:app];
}
Any links to tutorials attempting to do this, suggestions towards what I should do, or improvements to what I have would be greatly appreciated.
This should fix the problem:
// This is inside viewDidLoad
UIApplication *myApp = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:myApp];
// This is inside my table view - where I'm loading the file data to display in table cells
NSString *myPath = [self dataFilePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if (fileExists) {
NSArray *values = [[NSArray alloc] initWithContentsOfFile:myPath];
for (int i = 0; i < values.count; i++) {
cell.historyDisplay.text = [NSString stringWithFormat:#"%#", [values objectAtIndex:i]];
}
}
// This is the file path for history.plist
- (NSString *)dataFilePath {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[path objectAtIndex:0] stringByAppendingString:#"history.plist"];
}
// This is my search button - I want to save whatever was typed in the text field, into history.plist, to display in my tableview whenever a user goes to it.
- (IBAction)saveHistory:(id)sender {
NSMutableArray *values = [[NSMutableArray alloc]initWithContentsOfFile:[self dataFilePath]];
if(searchInputTextField.text.length > 0)
[values addObject:searchInputTextField.text];
[values writeToFile:[self dataFilePath] atomically:YES];
[leTableView reloadData];
}
I would use my suggest in comments, but here's some edits to your code that might help in the meantime.
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
for (int i = 0; i <array.count; i++) {
//I don't know what this line means
UITextField *theField = self.searchHistory;
//Change this line to this
theField.text = [NSString stringWithFormat:#"%#", [array objectAtIndex:i]];
}
I would use Core Data, creating a class, i.e. HistoryRecord with attributes termSearched and timestamp of type NSString and NSDate respectively.
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface HistoryRecordManagedObject : NSManagedObject
#property (nonatomic, retain) NSString *termSearched;
#property (nonatomic, retain) NSDate *timestamp;
+ (NSArray *)findEntity:(NSString *)entity withPredicate:(NSPredicate *)predicate
#end
Implementation
#import "HistoryRecordManagedObject.h"
#implementation HistoryRecordManagedObject
#dynamic termSearched;
#dynamic timstamp;
+ (NSArray *)findEntity:(NSString *)entity withPredicate:(NSPredicate *)predicate
{
NSError *error;
NSArray *fetchedObjects;
/* After set all properties, executes fetch request */
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:entity
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entityDesc];
[fetchRequest setPredicate:predicate];
fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
return fetchedObjects;
}
#end
Of course that's not just this! There are some extra stuff that must be done to use Core Data such as create the model. Read a little about it! It's worth!
Good luck!
In the action for searching, just save the search result to NSUserDefaults.
NSMutableArray *searches = [[NSUserDefaults standardUserDefaults] arrayForKey:#"searches"];
[searches insertObject:textField.text atIndex:0];
[[NSUserDefaults standardUserDefaults] setObject:searches forKey:#"searches"];
[[NSUserDefaults standardUserDefaults] synchronize];
Then load the same array for the tables data source and reload the table in viewwillappear and when keyboard is dismissed.
Replace your saveHistory function by below way:
- (IBAction)saveHistory:(id)sender
{
NSMutableArray *values = [[NSMutableArray alloc]initWithContentsOfFile:[self dataFilePath]];
if(searchInputTextField.text.length > 0)
[values addObject:searchInputTextField.text];
[values writeToFile:[self dataFilePath] atomically:YES];
[leTableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return values.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [values objectAtIndex:indexPath.row];
}

Credential editing in Plist if Correct

In plist I have stored Credentials from that I need to check for the correct Credential and if the correct Credential match then replace the password field with the new..for this I Have 3 UITextField . A for new email-id ,b for current password and c for new password ..if a==b means current password == email id then new password entered in the c textfield should replace in the current password field in plist
.
- (void)authenticateCredentials {
NSMutableArray *plistArray = [NSMutableArray arrayWithArray:[self readFromPlist]];
for (int i = 0; i< [plistArray count]; i++)
{
id object = [plistArray objectAtIndex:i];
if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *objDict = (NSDictionary *)object;
if ([[objDict objectForKey:#"pass"] isEqualToString:emailTextFeild.text] && [[objDict objectForKey:#"title"] isEqualToString:passwordTextFeild.text])
{
NSLog(#"Correct credentials");
// what should be the condition to replace current password to new password
}
NSLog(#"INCorrect credentials");
} else {
NSLog(#"Error! Not a dictionary");
}
}
}
Check if this will work for you.
- (void)authenticateCredentials {
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"XYZ.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:documentPlistPath];
NSArray *plistArray = [dict objectForKey:#"title"];
NSMutableArray *plistUpdatedArray = [NSMutableArray arrayWithArray:plistArray];
for (int i = 0; i< [plistArray count]; i++)
{
id object = [plistArray objectAtIndex:i];
if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *objDict = (NSDictionary *)object;
if ([[objDict objectForKey:#"pass"] isEqualToString:emailTextFeild.text] && [[objDict objectForKey:#"title"] isEqualToString:passwordTextFeild.text])
{
NSLog(#"Correct credentials");
NSMutableDictionary *dict1 = [NSMutableDictionary dictionaryWithDictionary:objDict];
[dict1 setObject:newPassword forKey:#"title"];
[plistUpdatedArray replaceObjectAtIndex:i withObject:dict1];
NSMutableDictionary *dict2 = [NSMutableDictionary dictionaryWithDictionary:dict];
[dict2 setObject:plistUpdatedArray forKey:#"title"];
[dict2 writeToFile:documentPlistPath atomically:YES];
return;
}
NSLog(#"INCorrect credentials");
} else {
NSLog(#"Error! Not a dictionary");
}
}
}
If your plist is in bundle you can't change the value stored in it.
So copy it to document directory before doing any change.
Answer to your question:
if([emailField.text isEqualToString:currntPwd.txt])
{
NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
[newDict addEntriesFromDictionary:objDict];
[newDict setObject:#"Midhun" forKey:#"pass"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *docDirectory = [paths objectAtIndex:0];
NSString *plistPath = [docDirectory stringByAppendingPathComponent:#"yourPlist.plist"];
[[NSFileManager defaultManager] removeItemAtPath:plistPath];
[newDict writeToFile:plistPath atomically:YES];
}

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.

Comparing with NSMutableArray

In my Array 1, which I loaded images from NSDocumentDirectory, I loaded them and add a NSMutableDictionary:
self.images = [NSMutableArray array];
for(int i = 0; i <= 8; i++)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"Images%d.png", i]];
if([[NSFileManager defaultManager] fileExistsAtPath:savedImagePath]){
NSMutableDictionary *container = [[NSMutableDictionary alloc] init];
[container setObject:[UIImage imageWithContentsOfFile:savedImagePath] forKey:#"image"];
[container setObject:[NSNumber numberWithInt:i] forKey:#"index"];
[images addObject:container];
}
}
In my other array Array 2, I loaded them from the app.
self.images = [NSMutableArray arrayWithObjects:
#"01.jpg",#"02.jpg",#"03.jpg",#"04.jpg",#"05.jpg",#"06.jpg",#"07.jpg",nil];
I was able to add string to Array 2 like this:
for (int x=1; x<8;x++) {
// add as NSString
[images addObject:[NSString stringWithFormat:#"%d", x]];
}
And was able to compare Array 2 like this:
NSInteger index = carousel.currentItemIndex;
if ([[images objectAtIndex:index] intValue] == 1){
What I wanted to do, is to do it to Array 1.
I know Array 1 has been already added with NSNumber, but Im kinda new to NSMutableDictionary so I can't do it the same as Array 2.
Can it be done the same as my Array 2 or what is the other way?
Thanks for the help.
Actually Here you have the array of dictionaries, because you are adding the dictionary which has two objects with keys image and index
So, for retrieving the array of dictionaries,
just log it and see what happens
Edit 2.0
for(int i=0; i< [images count]; i++){
NSNumber *num =[[images objectAtIndex:i] objectForKey:#"index"];
int index = [num intValue];
NSLog(#"%d",index)
}

How to iterate through an NSArray containing NSDictionaries?

I have an NSArray of NSDictionaries each of which has 4 key values.
I'm creating objects for each NSDictionary and assigning the keys accordingly.
How can I iterate through the array of dictionaries and set each key as an attribute for the object?
I created the array seen in the picture below with this code:
if (muscleArray == nil)
{
NSString *path = [[NSBundle mainBundle]pathForResource:#"data" ofType:#"plist"];
NSMutableArray *rootLevel = [[NSMutableArray alloc]initWithContentsOfFile:path];
self.muscleArray = rootLevel;
}
NSMutableArray *arrayForSearching = [NSMutableArray array];
for (NSDictionary *muscleDict in self.muscleArray)
for (NSDictionary *excerciseDict in [muscleDict objectForKey:#"exercises"])
[arrayForSearching addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[excerciseDict objectForKey:#"exerciseName"], #"exerciseName",
[muscleDict objectForKey:#"muscleName"], #"muscleName",
[muscleDict objectForKey:#"musclePicture"], #"musclePicture", nil]];
self.exerciseArray = arrayForSearching;
NSString *path = [[NSBundle mainBundle] pathForResource:#"ExerciseDescriptions"
ofType:#"plist"];
NSDictionary *descriptions = [NSDictionary dictionaryWithContentsOfFile:path];
NSMutableArray *exercises = self.exerciseArray;
for (NSInteger i = 0; i < [exercises count]; i++) {
NSDictionary *dict = [[exercises objectAtIndex:i] mutableCopy];
NSString *exerciseName = [dict valueForKey:#"exerciseName"];
NSString *description = [descriptions valueForKey:exerciseName];
[dict setValue:description forKey:#"exerciseDescription"];
[exercises replaceObjectAtIndex:i withObject:dict];
}
The code to create one object would look like this:
PFObject *preloadedExercises = [[PFObject alloc] initWithClassName:#"preloadedExercises"];
[preloadedExercises setObject:exerciseName forKey:#"exerciseName"];
[preloadedExercises saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
NSLog(#"Success");
} else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
The array of dictionaries looks like this:
// Assuming you want to do something with all of these objects you're creating
// We'll start by creating an NSMutableArray
NSMutableArray *newObjects = [NSMutableArray arrayWithCapacity:arrayOfDictionaries.count];
for (NSDictionary *dictionary in arrayOfDictionaries)
{
PFObject *object = [PFObject objectWithClassName:#"preloadedExercises"];
object.exerciseDescription = [dictionary objectForKey:#"exerciseDescription"];
object.exerciseName = [dictionary objectForKey:#"exerciseName"];
object.muscleName = [dictionary objectForKey:#"muscleName"];
object.musclePicture = [dictionary objectForKey:#"musclePicture"];
// Add object to mutable array
[newObjects addObject:object];
}
After a quick glance at the Parse SDK that you mentioned in the comments, I think what you are looking for is this:
NSMutableArray *exercisesArray = [[NSMutableArray alloc] init];
PFObject *preloadedExercises;
id value;
// Iterate through your array of dictionaries
for (NSDictionary *muscleDict in self.muscleArray) {
// Create our object
preloadedExercises = [PFObject objectWithClassName:#"preloadedExercises"];
// For each dictionary, iterate through its keys
for (id key in muscleDict) {
// Grab the value
value = [muscleDict objectForKey:key];
// And assign each attribute of the object to the corresponding values
[preloadedExercises setObject:value forKey:key];
}
// Finally, add this newly created object to your array
[exercisesArray addObject: preloadedExercises];
}
for(NSDictionary* dictionary in yourArray){
// here you can iterate through. and assign every dictionary as you wish to.
}