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"]
开发者_Python百科 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;
}
精彩评论