简体   繁体   中英

Retrieve data from sqLite database ios iphone application

I'm building a database and i would like to retrieve specific data from objects saved in the database.

This is the code i have:

//databaseMainViewController.m
//Create and database and save data

@implementation databaseMainViewController

@synthesize customer, code1,code2;


-(void) createTable: (NSString*)tableName
         withField1: (NSString*)field1
         withField2: (NSString*)field2
         withField3: (NSString*)field3
         withField4: (NSString*)field4; {

    char*err;
    NSString*sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS '%@' ('%@'"
                                              "TEXT PRIMARY KEY, '%@'TEXT, '%@'TEXT, '%@'TEXT);", tableName, field1, field2, field3, field4];

    if(sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err)!=SQLITE_OK){

        sqlite3_close(db);
        NSAssert(0, @"DCould not create table");

    }

    else {
        NSLog(@"table created");
    }
}

//file path to database
-(NSString*)filePath {
    NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[paths objectAtIndex:0]stringByAppendingPathComponent:@"bp.sql"];
}

//open database
-(void)openDB {

    if(sqlite3_open([[self filePath]UTF8String], &db) !=SQLITE_OK) {
        sqlite3_close(db);
        NSAssert(0, @"Databese failed to open");
    }

        else {
            NSLog(@"database opemed");
        }


}

- (IBAction)save:(id)sender {

    NSString*customers = customer.text;
    NSString*codeOne = code1.text;
    NSString*codeTwo = code2.text;
    NSDate*theDate = [NSDate date];

    NSString*sql= [NSString stringWithFormat:@"INSERT INTO summary ('theDate','customer','code1','code2')VALUES ('%@','%@','%@','%@')", theDate, customers,codeOne, codeTwo];

    char*err;

    if(sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err)!=SQLITE_OK){

        sqlite3_close(db);
        NSAssert(0, @"Could not update table");

    }

    else {
        NSLog(@"table updated");
    }

    customer.text = @"";
    code1.text = @"";
    code2.text = @"";



}

- (void)viewDidLoad
{
    [self openDB];
    [self createTable:@"summary" withField1:@"theDate" withField2:@"customer" withField3:@"code1" withField4:@"code2"];
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

Then I have code to retrieve data and put them in a main list

#import "databaseFlipsideViewController.h"
#import "detailViewController.h"


@interface databaseFlipsideViewController ()

@end

@implementation databaseFlipsideViewController

@synthesize entries;

//file path to database
-(NSString*)filePath {
    NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[paths objectAtIndex:0]stringByAppendingPathComponent:@"bp.sql"];
}

//open database
-(void)openDB {

    if(sqlite3_open([[self filePath]UTF8String], &db) !=SQLITE_OK) {
        sqlite3_close(db);
        NSAssert(0, @"Databese failed to open");
    }

    else {
        NSLog(@"database opemed");
    }


}

- (void)viewDidLoad
{
    entries = [[NSMutableArray alloc]init];
    [self openDB];
    NSString*sql = [NSString stringWithFormat:@"SELECT * FROM summary"];
    sqlite3_stmt*statement;

    if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK) {

        while (sqlite3_step(statement)==SQLITE_ROW) {
            char*field1 = (char*)sqlite3_column_text(statement, 0);
            NSString*field1Str = [[NSString alloc]initWithUTF8String:field1];

            char*field2 = (char*)sqlite3_column_text(statement, 1);
            NSString*field2Str = [[NSString alloc]initWithUTF8String:field2];

            char*field3 = (char*)sqlite3_column_text(statement, 2);
            NSString*field3Str = [[NSString alloc]initWithUTF8String:field3];

            char*field4 = (char*)sqlite3_column_text(statement, 3);
            NSString*field4Str = [[NSString alloc]initWithUTF8String:field4];

            NSString*str = [[NSString alloc]initWithFormat:@"%@", field2Str ];
            [entries addObject:str];
        }
    }

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Actions

- (IBAction)done:(id)sender
{
    [self.delegate flipsideViewControllerDidFinish:self];
}

-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {

    //Return the number of sections
    return 1;
}

-(NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section {
    NSString*myTitle = [[NSString alloc]initWithFormat:@"History"];
    return myTitle;
}

-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{

    return [entries count];
    NSLog(@"%d",[entries count]);


}

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"test");

    static NSString*cellIdentifier = @"Cell";
    UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    cell.textLabel.text = [self.entries objectAtIndex:indexPath.row];
    return cell;

}

And after this I have a problem, because when i click at one of the names out of the list, the application goes to another view with details about the name. But the details by every name are the same.

This is the code for the detailViewController:

#import "detailViewController.h"

@interface detailViewController ()

@end

@implementation detailViewController

@synthesize customerLabel,code1Label,code2Label,dateLabel;

//file path to database
-(NSString*)filePath {
    NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[paths objectAtIndex:0]stringByAppendingPathComponent:@"bp.sql"];
}

//open database
-(void)openDB {

    if(sqlite3_open([[self filePath]UTF8String], &db) !=SQLITE_OK) {
        sqlite3_close(db);
        NSAssert(0, @"Databese failed to open");
    }

    else {
        NSLog(@"database opemed");
    }


}

- (IBAction)back:(id)sender
{
    [self.delegate detailViewControllerDidFinish:self];
}

- (void)viewDidLoad
{
    [self openDB];
    NSString*sql = [NSString stringWithFormat:@"SELECT * FROM summary"];
    sqlite3_stmt*statement;


    if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK) {

        while (sqlite3_step(statement)==SQLITE_ROW) {


            char*field1 = (char*)sqlite3_column_text(statement, 0);
            NSString*field1Str = [[NSString alloc]initWithUTF8String:field1];

            char*field2 = (char*)sqlite3_column_text(statement, 1);
            NSString*field2Str = [[NSString alloc]initWithUTF8String:field2];

            char*field3 = (char*)sqlite3_column_text(statement, 2);
            NSString*field3Str = [[NSString alloc]initWithUTF8String:field3];

            char*field4 = (char*)sqlite3_column_text(statement, 3);
            NSString*field4Str = [[NSString alloc]initWithUTF8String:field4];



            customerLabel.text = field2Str;
            code1Label.text = field3Str;
            code2Label.text =field4Str;
            dateLabel.text = field1Str;

        }
    }

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

So what is the best way to display the details from the selected object in the detail screen

This solution works for me

I have add this code to databaseFlipsideViewController

//databaseFlipsideViewController.m

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        detailController = segue.destinationViewController;
        detailController.customerName = [keys objectAtIndex:indexPath.row];
        NSLog(@"%@", detailController.customerName);
  }
}

And my detailViewController code is this:

@implementation detailViewController

@synthesize customerLabel,code1Label,code2Label,dateLabel,customerName,code1Name;

//file path to database
-(NSString*)filePath {
    NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[paths objectAtIndex:0]stringByAppendingPathComponent:@"bp.sql"];
}

//open database
-(void)openDB {

    if(sqlite3_open([[self filePath]UTF8String], &db) !=SQLITE_OK) {
        sqlite3_close(db);
        NSAssert(0, @"Databese failed to open");
    }

    else {
        NSLog(@"database opemed");
    }


}

- (IBAction)back:(id)sender
{
    [self.delegate detailViewControllerDidFinish:self];
}

- (void)viewDidLoad
{

    [self openDB];
    NSString*sql = [NSString stringWithFormat:@"SELECT theDate, customer,code1,code2 FROM summary WHERE key=\"%@\"", customerName];
     const char *query_stmt = [sql UTF8String];
    sqlite3_stmt*statement;

    if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, nil)==SQLITE_OK) {

        if (sqlite3_step(statement)==SQLITE_ROW) {

            NSString *date = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
            dateLabel.text = date;

            NSString *customer = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
            customerLabel.text = customer;

            NSString *code1 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
            code1Label.text = code1;

            NSString *code2 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement,3)];
            code2Label.text = code2;

        }
        sqlite3_finalize(statement);

            [super viewDidLoad];
        }
    sqlite3_close(db);
    }

Because in - (void)viewDidLoad from detailViewController your select query does not specify a user/summary , rather than that, it selects everything .

In your while the loop, you overwrite all the labels properties for each row from your database. So the result will always look the same, the last result from the database is displayed..

The answer would be to implement the tableView's didSelectRowAtIndexPath function, and pass the ID of the user to the detailView controller, where you then use a more specific query to fetch the right entry, ie:

@"SELECT * FROM x WHERE id = '%@'", _id;

But really I think you need a basic lesson SQL..

Protip: consider using Core Data, it's meant for this. You really only want SQLite on your iPhone when Core Data is to limiting in features or performance..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM