edit tableView and delete Document file - iphone

i've a tabBarController with 4 viewController.
One of this is a TableViewController.
In viewDidLoad of the tableView i inizialize 2 NSMutableArray
list = [[NSMutalbeArray alloc] init];
dates = [[NSMutalbeArray alloc] init];
in viewDidAppear i add objects
NSError *error;
NSError *error1;
fileManager = [NSFileManager defaultManager];
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsPath = [paths objectAtIndex:0];
for (NSString *file in [fileManager contentsOfDirectoryAtPath:docsPath error:&error]) {
fileFrom = [docsPath stringByAppendingPathComponent:file];
NSDictionary* properties = [[NSFileManager defaultManager]
attributesOfItemAtPath:fileFrom
error:&error1];
NSDate* modDate = [properties objectForKey:NSFileModificationDate];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale: [NSLocale currentLocale]];
[dateFormatter setDateStyle:kCFDateFormatterMediumStyle];
[dateFormatter setTimeStyle:kCFDateFormatterNoStyle];
NSString* dateString = [dateFormatter stringFromDate:modDate];
BOOL isDir;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:#"%#/%#", docsPath, file] isDirectory:&isDir];
if (exists && !isDir && ![file hasPrefix:#"."]) {
[list addObject:file];
[dates addObject:dateString];
}
}
[[self tableView] reloadData];
where every file is a filename in my documentDirectory and dateString the creation date.
I can visualize in my tableView the list of file.
If i edit the tableView and try to delete element it works, i can remove the element both from filesystem and on the tableView BUT if i add a new file to my document directory (like the apps do) i receive an EXE_BAD_ADDRESS
- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSString *temp = [list objectAtIndex:indexPath.row];
NSString *lastPath = [docsPath stringByAppendingPathComponent:temp];
[fileManager removeItemAtPath:lastPath error:nil];
[self.list removeObjectAtIndex:indexPath.row];
[self.dates removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
[self.tableView reloadData];
}
}
Any advise?

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];
}

loading data from plist to another class

In my app, plist files are being saved to the documents directory, each file name is the current date+time.
I'm loading the list of files from the documents directory to a table: filesTableVC.m.
Each time I want to load the chosen file to a new class: oldFormVC.m
but this class is opened empty.
I'm not sure where the problem is.
filesTableVC.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
oldFormVC *oldForm = [[oldFormVC alloc] initWithNibName:nil bundle:nil];
//load previous data:
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:[fileList objectAtIndex:indexPath.row]];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property liost into dictionary object
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp)
{
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
// assign values
self.theDate = [temp objectForKey:#"theDate"];
self.theTime = [temp objectForKey:#"theTime"];
self.carNumber = [temp objectForKey:#"carNumber"];
self.driverName = [temp objectForKey:#"driverName"];
[self presentViewController:oldForm animated:YES completion:nil];
}
oldFormVC.m:
- (void)viewDidLoad
{
[super viewDidLoad];
dateField.text = theDate;
timeField.text = theTime;
carNumberField.text = carNumber;
driverNameField.text = driverName;
}
Write your code in viewDidAppear
- (void)viewDidAppear:(BOOL)animated
{
dateField.text = theDate;
timeField.text = theTime;
carNumberField.text = carNumber;
driverNameField.text = driverName;
}
Also, change this code in filesTableVC.m:
oldForm.dateField = [temp objectForKey:#"theDate"];
oldForm.theTime = [temp objectForKey:#"theTime"];
oldForm.carNumber = [temp objectForKey:#"carNumber"];
oldForm.driverName = [temp objectForKey:#"driverName"];
Hope it helps you

How To Split NSMutableArry Data into Two parts?

I am Working on Recording Application.in This Application i Save my Recording with my own Text and it also Save the Recording with Current Date and Time.As my below Code show
-(IBAction)RecButtonPress:(id)sender
{
NSLog(#"Song name:%#",mySongname);
NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44000.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
[recordSetting setValue: [NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[recordSetting setValue: [NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
NSDate* now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd:MMM:YY_hh:mm:ss a"];
NSString *file= [dateFormatter stringFromDate:now];
NSString *fina=[file stringByAppendingString:mySongname];
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:#"MyRecordings"];
if (![[NSFileManager defaultManager] fileExistsAtPath:soundFilePath])
[[NSFileManager defaultManager] createDirectoryAtPath:soundFilePath withIntermediateDirectories:NO attributes:nil error:nil];
soundFilePath = [soundFilePath stringByAppendingPathComponent:fina];
recordedTmpFile = [NSURL fileURLWithPath:soundFilePath];
NSLog(#"Uf:%#",recordedTmpFile);
recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];
[recorder setDelegate:self];
[recorder prepareToRecord];
[recorder record];
[recordSetting release];
[dateFormatter release];
}
Now After Saving Recording When i goes to SaveRecording Class Where actually i Show all these Recording in Tableview.here my Code is
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentPath = [documentsDirectory stringByAppendingPathComponent:#"MyRecordings"];
directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath:documentPath];
NSLog(#"file found %i",[directoryContent count]);
NSLog(#"arraydata: %#", directoryContent );
[directoryContent retain];
[self.tableView reloadData];
}
And After That i Assign "directoryContent" Which is my NSMutablArray To UITableview.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [directoryContent count];
}
//////////////////////////////////////////////////////////////////////////////////////////////
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
static NSInteger StateTag = 1;
static NSInteger CapitalTag = 2;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UILabel *capitalLabel = [[UILabel alloc] initWithFrame:CGRectMake(2, 2, 120, 20)];
//capitalLabel.text=#"mydata";
capitalLabel.backgroundColor=[UIColor redColor];
capitalLabel.tag = CapitalTag;
[capitalLabel setFont:[UIFont systemFontOfSize:9]];
[cell.contentView addSubview:capitalLabel];
[capitalLabel release];
UILabel *stateLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 22, 310, 20)];
stateLabel.tag = StateTag;
[stateLabel setFont:[UIFont systemFontOfSize:14]];
stateLabel.adjustsFontSizeToFitWidth=YES;
[cell.contentView addSubview:stateLabel];
[stateLabel release];
}
UILabel * stateLabel = (UILabel *) [cell.contentView viewWithTag:StateTag];
//UILabel * capitalLabel = (UILabel *) [cell.contentView viewWithTag:CapitalTag];
stateLabel.text = [directoryContent objectAtIndex:indexPath.row];
//capitalLabel.text = [datesaving objectAtIndex:indexPath.row];
return cell;
}
And Finaly my UITableView is Look like this Below ScreenShot
My All this Brief discussion purpose is that as my Screen shot show That UITableview Cell Show my Text and Current date and Time.Now i want to Split this directoryContent Array data into Two prats.The part which Consist of Current date and time i want to Assign it capitalLabel which is redpart of Cell in UITableview And Text to stateLabel Which is Below part of Cell in UITableview.Any help will be Appriated.Thanks in Advance.
First you need to append your string like this
NSString *file3 = [file stringByAppendingString:#"+"];
NSString *fina= [file3 stringByAppendingString:mySongname];
after that you need to seperate it like
NSArray *Array = [str componentsSeparatedByString:#"+"];
NSLog(#"myindex0str:%#",[Array objectAtIndex:0]);
NSLog(#"myindex1str:%#",[Array objectAtIndex:1]);
so you will get the both time and songname individually.
Hi Lena you can try the following things
1) Array of Dictionary
Save your Date and Song name separately in a Dictionary
NSDictionary *myData = [NSDictionary dictionaryWithObjectsAndKeys:myDateObj,#"SongDate",mySongName,#"SongName", nil];
[myMutableArray addObject:myData]//myMutableArray is a NSMutableArray;
Now you can use it as follows
NSDictionary *dict = [directoryContent objectAtIndex:indexPath.row];
stateLabel.text = [dict objectForKey:#"SongName"];
capitalLabel.text = [dict objectForKey:#"SongDate"];
OR
2) Your can do a little trick :)
NSString *fina=[file stringByAppendingFormat:#"+%#",mySongname];
NSArray *Array = [fina componentsSeparatedByString:#"+"];
capitalLabel.text = [Array objectAtIndex:0];
stateLabel.text = [Array objectAtIndex:1];
Here while appending you can use format and add any special character which you can use later to split the string.
Hope this will help you in any ways :)

How to Save Current date and time values in Document Directory?

As my above screen shot show that I want to show Two values in Each cell of Tableview. I can do it if I have the data which I want to show in these labels of Cell in the same Class,but problem for me is I am try to getting both these labels from other view or other class using (NSDocumentDirectory, NSUserDomainMask, YES) so for I got success to show one value as my screenshot show ,but the other part which consist of current data and time Display is still problem for me.Now here is my code which i try so for.
NSString *fina = [NSString stringWithFormat:#"%#",mySongname];
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:#"MyRecordings"];
if (![[NSFileManager defaultManager] fileExistsAtPath:soundFilePath])
[[NSFileManager defaultManager] createDirectoryAtPath:soundFilePath withIntermediateDirectories:NO attributes:nil error:nil];
soundFilePath = [soundFilePath stringByAppendingPathComponent:fina];
recordedTmpFile = [NSURL fileURLWithPath:soundFilePath];
recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];
[recorder setDelegate:self];
[recorder prepareToRecord];
[recorder record];
[recordSetting release];
The above part of Code works fine it display the value in Tableview Cell that my screenshow.Now in same function I am try to getting the data to show it in red part which is my UILabel in Tableview Cell using Below Code.
NSDate* now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd:MMM:YY_hh:mm:ss a"];
NSString *file= [dateFormatter stringFromDate:now];
NSLog(#"myfinaldate:%#",file);
Now i want to save this date value in same directory which i use above and to show it red parts of UITableview .
Now here is my Code where i use this Tableview and getting these document directory value.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentPath = [documentsDirectory stringByAppendingPathComponent:#"MyRecordings"];
directoryContent = [[NSFileManager defaultManager] directoryContentsAtPath:documentPath];
NSLog(#"file found %i",[directoryContent count]);
[directoryContent retain];
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
static NSInteger StateTag = 1;
static NSInteger CapitalTag = 2;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UILabel *capitalLabel = [[UILabel alloc] initWithFrame:CGRectMake(2, 2, 80, 20)];
//capitalLabel.text=#"mydata";
capitalLabel.backgroundColor=[UIColor redColor];
capitalLabel.tag = CapitalTag;
[cell.contentView addSubview:capitalLabel];
[capitalLabel release];
UILabel *stateLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 22, 310, 20)];
stateLabel.tag = StateTag;
[stateLabel setFont:[UIFont systemFontOfSize:14]];
stateLabel.adjustsFontSizeToFitWidth=YES;
[cell.contentView addSubview:stateLabel];
[stateLabel release];
}
UILabel * stateLabel = (UILabel *) [cell.contentView viewWithTag:StateTag];
//UILabel * capitalLabel = (UILabel *) [cell.contentView viewWithTag:CapitalTag];
stateLabel.text = [directoryContent objectAtIndex:indexPath.row];
//capitalLabel.text = [directoryContent1 objectAtIndex:indexPath.row];
return cell;
}
Now I am trying to summarize the problem.
How we can save the date and time value in same directory and then how to show here in Red part of UITableview Cell?
capitalLabel is my Redpart of Cell to show date and time which is problem.
stateLabel all ready show the values. so no problem with this label. Any help will be appreciated.
just do this....
you can set NSCachesDirectory to NSDocumentDirectory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:yourComponent];
// NSLog(#"Path : %#",writableDBPath);
NSMutableDictionary *plistArr = [[NSMutableDictionary alloc] initWithContentsOfFile:writableDBPath];

Selected row in UITableView shows a different result in the next TabBarViewController

I have been trying to figure out what went wrong with this segment in my code. It was working fine for a normal UITableView, which has data extracted from a local database (results after clicking a button).
However, after I used this similar code for a UITableView that shows results of a search (I was trying to do a multiple category search but failed), there has been errors, differences between the selected row and the outcome or results on the TabBarViewController.
Following is my code for the linkage to the TabBarViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
TabBarViewController *tabBarView = [[TabBarViewController alloc] initWithNibName:#"TabBarViewController" bundle:[NSBundle mainBundle]];
Attraction *att = [attractions objectAtIndex: indexPath.row];
tabBarView.attraction = att;
[self.navigationController presentModalViewController:tabBarView animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tabBarView release];
}
Here are my full codes for you to inspect:
-(void) checkAndCreateDatabase{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
databaseName = #"funsg.sql";
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
//NSLog([NSString stringWithFormat:#"GetData %#", databasePath]);
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
[fileManager release];
}
-(void)createEditableCopyOfDatabaseIfNeeded {
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"abc.sql"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"abc.sql"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
-(void) readAttractionsFromDatabase {
[self checkAndCreateDatabase];
// Open the database
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = [[NSString stringWithFormat:#"select * from everything "] UTF8String];
//NSLog([NSString stringWithFormat:#"select * from everything"]);
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSString *bus = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
NSString *desc = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *location = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *mrt = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSString *name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 4)];
NSString *image = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 5)];
NSString *type = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 6)];
NSString *carpark = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 7)];
// Create a new animal object with the data from the database
Attraction *att = [[Attraction alloc] initWithName:desc buses:bus add:location type:type mrt:mrt image:image name:name carpark:carpark];
if (attractions == NULL)
// There should not be a NULL name
NSLog(#"Null name!!");
else {
[attractions addObject:att];
// Apparently the addObject function in NSMutableArray does not
// keep a copy of our object, so, we can't release it.
//[name release];
[att release];
}
}
sqlite3_finalize(compiledStatement); // Cleanup the statement
}
else {
NSLog(#"Error retrieving data from database.");
}
sqlite3_close(database);
}
else {
NSLog(#"Error: Can't open database!");
}
}
-(void)viewDidLoad {
[super viewDidLoad];
attractions = [[NSMutableArray alloc] init];
searchedNames = [[NSMutableArray alloc] init];
[self loadData];
}
-(void) insertToDB :(Attraction*) att {
[self checkAndCreateDatabase];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
static sqlite3_stmt *compiledStatement;
sqlite3_exec(database, [[NSString stringWithFormat:#"INSERT INTO everything (Bus,Description,Location,MRT,Name,image,type,Carpark) SELECT '%#','%#','%#','%#', '%#', '%#', '%#', '%#' WHERE NOT EXISTS (SELECT 1 FROM everything WHERE Name = '%#');", att.buses,att.desc,att.add, att.mrt, att.name, att.image, att.type , att.carpark,att.name] UTF8String], NULL, NULL, NULL);
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
-(void) loadData {
//First fetch the data from the JSON
NSURL *url = nil;
NSString *querystring = [NSString stringWithFormat:#"http://mp15.bitproj1.com/testsearch.php"];
url = [NSURL URLWithString:querystring];
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url];
//NSLog(#"jsonreturn"); // Look at the console and you can see what the restults are
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
// In "real" code you should surround this with try and catch
self.data = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (data==nil){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Internet Connection" message:#"Unable to update the data." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
else
{
self.rows =[data objectForKey:#"attractions"];
for (int i=0; i<[self.rows count]; i++) {
NSDictionary *dict = [rows objectAtIndex: i];
Attraction* a = [[Attraction alloc] initWithName:[dict objectForKey:#"Description"]
buses:[dict objectForKey:#"Bus"]
add:[dict objectForKey:#"Location"]
type:[dict objectForKey:#"type"]
mrt:[dict objectForKey:#"MRT"]
image:[dict objectForKey:#"image"]
name:[dict objectForKey:#"Name"]
carpark:[dict objectForKey:#"Carpark"]];
//Here we insert the data, when inserting we check for the duplicates. If the record already exists we do not insert. Code also must be optimized later
[self insertToDB:a];
}
}
[jsonreturn release];
[self readAttractionsFromDatabase];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return(1);
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return([searchedNames count]);
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *cellText = [searchedNames objectAtIndex:indexPath.row];
[cell.textLabel setText:cellText];
return cell;
}
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[searchedNames removeAllObjects];// remove all data that belongs to previous search
if([searchText isEqualToString:#""] || searchText==nil) {
// Nothing to search, empty result.
[myTableView reloadData];
return;
}
for (NSString *att in attractions) {
Attraction* p = ((Attraction *)att);
NSRange r = [p.name rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(r.location != NSNotFound) {
[searchedNames addObject:p.name];
}
}
[myTableView reloadData];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
TabBarViewController *tabBarView = [[TabBarViewController alloc] initWithNibName:#"TabBarViewController" bundle:[NSBundle mainBundle]];
Attraction *att = [attractions objectAtIndex: indexPath.row];
tabBarView.attraction = att;
[self.navigationController presentModalViewController:tabBarView animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tabBarView release];
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void)viewDidUnload {
}
-(void)dealloc {
[data release];
[attractions release];
[super dealloc];
}
#end
Are you using two different array as datasource? If so, I think you are not retrieving the value from the correct array.
And also I can't understand the use of this code:
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
You can change that code as:
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
Edit
You are using two diff arrays searchedNames, attractions. There is the problem:
if(searching==YES)
{
//retrieve the values from searchedNames array
}
else
{
//retrieve the values from attractions array
}
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
searching=YES;
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
searching=NO;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(searching==YES)
return([searchedNames count]);
else
return [attractions count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *cellText;
if(searching==YES)
cellText = [searchedNames objectAtIndex:indexPath.row];
else
cellText = [attractions objectAtIndex:indexPath.row];
[cell.textLabel setText:cellText];
return cell;
}