I made a data.plist and want to load the root array (names) into a table view, then when you click on each cell, it will load their corresponding exercise array into a new table view. How would I implement this method into my TableViewController?
My current plist has a root array, with a dictionary item for each muscle group (Item 0, then child name) then contains an array for the muscle's exercises.
My didSelectRowAtIndexPath Method for the first table that pushes the 2nd view subtable is:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
ExerciseTableViewController *detailViewController = [[ExerciseTableViewController alloc] initWithNibName:#"AbdominalTableViewController" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
My viewDidLoad method for the 2nd table view controller (this needs to be fixed) is:
- (void)viewDidLoad
if (exerciseArray == nil)
{
NSString *path = [[NSBundle mainBundle]pathForResource:#"biceps" ofType:#"plist"];
NSMutableArray *array = [[NSMutableArray alloc]initWithContentsOfFile:path];
self.exerciseArray = array;
[array release];
Assuming i understand you question.
You can do something like:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *muscle = [muscles objectAtIndex:indexPath.row]; //'muscles' array is the first level of your plist
...
ExerciseTableViewController *detailViewController = [[ExerciseTableViewController alloc] initWithNibName:muscle bundle:nil];
detailViewController.muscle = muscle;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
...
}
And in the second controller:
...
NSString *path = [[NSBundle mainBundle]pathForResource:#"biceps" ofType:#"plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
self.exerciseArray = [plistDict objectForKey:muscle]; //'muscle' is the string you set in the previous controller
[plistDict release];
...
Hope it's help.
Edit after Faisal comment:
Using the following plist file:
For read this plist you can do:
//Read the plist file into an array (the root element is an array)
NSString *path = [[NSBundle mainBundle]pathForResource:#"Data" ofType:#"plist"];
NSArray *rootLevel = [[NSMutableArray alloc]initWithContentsOfFile:path];
Then for read the second level, the 'rootLevel' content:
NSDictionary *secondLevel = [rootLevel objectAtIndex:0];
NSString *muscle = [secondLevel valueForKey:#"name"]; //"Biceps" string
NSArray *exercises = [secondLevel valueForKey:#"exercises"]; //[exercises objectAtIndex:0] is "Biceps Curl" string
Related
when I delete images from tablecells in UITableView it use to get delete from tablecells as well as from server but when we click to open the other image in egophotoviewer the deleted image is still coming?..
Here is my code.
- (void)showSelectedPhoto:(NSIndexPath *)indexPath {
NSString *passingImageName = [[self.tableDataSource objectAtIndex:indexPath.row]objectForKey:#"fileName"];
NSMutableArray *photoArray = [self getFilteredArray];
NSMutableArray *urlsArray = [[NSMutableArray alloc] init];
for (NSString *string in photoArray) {
NSLog(#"String Values:%#", string);
NSURL *imageUrl = [self getEnlargedImageImageUrl:[self._prefix stringByAppendingString:string]];
NSLog(#"Passing url is:%#", imageUrl);
photo = [[EGOQuickPhoto alloc] initWithImageURL:imageUrl name:string];
[urlsArray addObject:photo];
}
if (!source) {
self.source = [[EGOQuickPhotoSource alloc] initWithPhotos:urlsArray];
}
photoController = [[EGOPhotoViewController alloc] initWithPhotoSource:source];
[self.navigationController pushViewController:photoController animated:YES];
NSUInteger index = [photoArray indexOfObject:passingImageName];
[photoController moveToPhotoAtIndex:index animated:NO];
}
After deleting the image you need to reload the tableview.
[tableView reloadData];
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];
}
This is my first time asking a question & posting code so I hope I have included everything that is necessary.
In several of my other apps I have been able to successfully reloadData in a UITableView but for some reason I cannot get it to work here.
I am using a navigationController and drilling down a few levels in the UITableView until a new class loads which right now just has two buttons that switch between 2 similar plist files so I can tell that the tableView is actually reloading (Data.plist & Data2.plist)
This is eventually going to be a timesheet sort of app where individual jobs are listed and the user (driver) will punch a timeclock with In/Out buttons. For now, what I want is to drill down and click the button that loads the other plist and go back up to reveal that the new plist data has loaded. My problem is that I cannot get the tableView to reload at all. I've tried putting different variations of [self.tableView reloadData] & [myTableView reloadData] (which I have also connected via IB) all over the place but none of them work. I'm currently calling a method in the rootViewController (where the tableView is) from detailViewController (where the buttons are) and that basic process works for me in other apps when there is no navigationController being used. The navigationController seems to be throwing me off here in this app. I hope an easy solution can be found. My code so far looks like this:
AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
RootViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
//THIS ESTABLISHES WHICH PLIST TO LOAD BASED ON THE BUTTON CLICKED
plistToUse = [[NSUserDefaults standardUserDefaults] objectForKey:#"plistToUse"];
if (plistToUse == #"Data.plist") {
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:#"Data.plist"];
NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:DataPath];
self.data = tempDict;
[tempDict release];
} else if (plistToUse == #"Data2.plist") {
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:#"Data2.plist"];
NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:DataPath];
self.data = tempDict;
[tempDict release];
} else {
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:#"Data.plist"];
NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:DataPath];
self.data = tempDict;
[tempDict release];
}
if(CurrentLevel == 0) {
NSArray *tempArray = [[NSArray alloc] init];
self.tableDataSource = tempArray;
[tempArray release];
self.tableDataSource = [self.data objectForKey:#"Rows"];
self.navigationItem.title = #"Choose Driver";
} else if (CurrentLevel == 1) {
self.navigationItem.title = #"Choose Day";
} else if (CurrentLevel == 2) {
self.navigationItem.title = #"Choose Job";
} else if (CurrentLevel == 3) {
self.navigationItem.title = #"Job Details";
} else {
self.navigationItem.title = CurrentTitle;
}
}
-(void)update {
dvController.labelHelper.text = #"UPDATED"; //USED TO SEE IF A LABEL IN THE BUTTON CLASS WILL UPDATE
NSArray *tempArray = [[NSArray alloc] init];
self.tableDataSource = tempArray;
[tempArray release];
self.tableDataSource = [self.data objectForKey:#"Rows"];
self.navigationController.navigationItem.title = #"Choose Driver";
self.navigationController.title = #"THE TITLE";
[myTableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
unsortedIndex=1;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.tableDataSource 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];
}
dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
cell.textLabel.text = [dictionary objectForKey:#"Title"];
NSArray *Children = [dictionary objectForKey:#"Children"];
if ([Children count] == 0) {
Titles = [dictionary objectForKey:#"Title"];
in1 = [[NSUserDefaults standardUserDefaults] objectForKey:#"InTime1"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", in1];
}
in1 = [[NSUserDefaults standardUserDefaults] objectForKey:#"InTime1"];
out1 = [[NSUserDefaults standardUserDefaults] objectForKey:#"OutTime1"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#:%#", in1, out1];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
NSArray *Children = [dictionary objectForKey:#"Children"];
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:[NSBundle mainBundle]];
if([Children count] == 0) {
[self.navigationController pushViewController:dvController animated:YES];
dvController.labelSiteName.text = [dictionary objectForKey:#"Company"];
dvController.labelSiteAddress.text = [dictionary objectForKey:#"Address"];
dvController.labelSiteNotes.text = [dictionary objectForKey:#"Notes"];
[dvController.mapView setMapType:MKMapTypeStandard];
[dvController.mapView setZoomEnabled:YES];
[dvController.mapView setScrollEnabled:YES];
dvController.mapView.showsUserLocation = YES;
[dvController release];
}
else {
RootViewController *rvController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:[NSBundle mainBundle]];
rvController.CurrentLevel += 1;
rvController.CurrentTitle = [dictionary objectForKey:#"Title"];
[self.navigationController pushViewController:rvController animated:YES];
rvController.tableDataSource = Children;
[rvController release];
}
}
DetailViewController.m
These are the two buttons that should reload the tableView with either Data.plist or Data2.plist
-(IBAction)getInTime1:(id)sender {
plistToUse = #"Data.plist";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:plistToUse forKey:#"plistToUse"];
[defaults synchronize];
[rvController update];
}
-(IBAction)getOutTime1:(id)sender {
plistToUse = #"Data2.plist";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:plistToUse forKey:#"plistToUse"];
[defaults synchronize];
[rvController update];
}
I appreciate any help you can give.
Add your data fetching from plist code into your viewDidAppear or viewWillAppear methods, so that each time view appears, the data is loaded from plist.
And also note that your arrays are allocated only once.
This will work for you.
i have an function in which i am calling values from dictionary that is defined in other view controller. I have to call this method in view didload method of current view controller.
here is my code:
-(void)setData:(NSDictionary *)dic {
self.jsonLabel.text = [dic objectForKey:#"Description"];
self.jsonImage.image = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: [dic objectForKey:#"PictureURL"]]]];}
Try this
NSURL *jsonURL = [NSURL URLWithString:[jsonItem objectForKey:#"PictureURL"]];
Update:
See you allocate the dictionary while the second View controller inside its alloc init method.
Then you can pass the dictionary from the first view controller as
secondViewController.dict = self.dict;
Then you push the second view controller. Check the value of the dictionary in viewDidLoad: Then you can proceed if the dictionary is available.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//make sure jscontroller is allocated before this point.
NSDictionary *tempDict = [[NSDictionary alloc]init];
// set tempDict here with value or object aBook.PictureURL.
jscontroller.jsonItem = tempDict;
[tempDict release];
NSLog(#"json ndic.......%#", jscontroller.jsonItem);
[self.navigationController pushViewController:jscontroller animated:YES];
}
If viewControllerObject is the necessary object of the view controller that defines this function then allocate the object and call like this
- (void)viewDidLoad {
[viewControllerObject setData:urDict];
}
I was using this code in otherviewcontroller
and trying to retrieve in currentViewController
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
JSONViewController *controller = [[JSONViewController alloc] initWithNibName:#"JSONView" bundle:nil];
EmpDictionary=[[NSMutableDictionary alloc]init];
[EmpDictionary setValue:aBook.Description forKey:#"Description"];
[EmpDictionary setValue:aBook.PictureURL forKey:#"PictureURL"];
[EmpDictionary setValue:aBook.WeatherID forKey:#"WeatherID"];
EmpArray=[[NSMutableArray alloc]init];
[EmpArray addObject:EmpDictionary];
NSDictionary *itemAtIndex = [self.EmpArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:controller animated:YES];
[controller setData:itemAtIndex];}
Okay, so I have an app that I'm trying to get to populate a UITableView with the contents of a plist file. I haven't been able to find anyone else having problems doing this and how they fixed it so I'm probably just an idiot but I need to know how all the same!
I'm sure the error is somewhere in my viewDidLoad section or my tableview section...but maybe someone else can give me a better idea.
-(void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"datam" ofType:#"plist"];
NSArray *array = [[NSArray alloc] initWithContentsOfFile:path];
self.listData = array;
[array release];
[super viewDidLoad];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.listData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"Identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
}
I think [super viewDidLoad] should be foremost in the viewDidLoad method.
NSString *path = [[NSBundle mainBundle] pathForResource:#"datam" ofType:#"plist"];
NSArray *array = [[NSArray alloc] initWithContentsOfFile:path];
This seems a little odd; is your file named "datam.plist"?
Try using some NSLogs() throughout your code to see what the status of your array is at any given time:
NSLog(#"%# has %i elements",ARRAY_OBJECT,[ARRAY_OBJECT count]);
Check the GDB output in XCode while the application runs to see if the results match what you expect.
self.listData = array; [array release];
Try this instead:
self.listData = [array copy]; [array release];
NSArray objects are pointers; when you set self.listData = array, you really tell anything looking for listData to look in the memory address originally occupied by array. When you release array, it vacates that memory address, thus making the pointer point to nothing.