在数据库中一次添加2行或3行无法在iPhone中添加记录

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在数据库中一次添加2行或3行无法在iPhone中添加记录相关的知识,希望对你有一定的参考价值。

我有一个应用程序,其中有一个系统添加按钮导航栏。单击添加按钮,将打开一个新页面,其中包含3个名为txtJourneyname,txtlocationName,txtdescription的文本字段。

在此页面上,导航上有一个保存按钮,因此当用户在文本字段中输入值并单击保存按钮时,值将保存在数据库中。但我遇到的问题是,当我一次添加2个或3个值时,只在数据库中输入第一个值。我希望我输入的所有值都必须保存在数据库中。

这是我的appdelegate代码:

    #import <UIKit/UIKit.h>
    @class NewJourney;
    @class JourneyController;


    @interface SqltestAppDelegate : NSObject <UIApplicationDelegate> {
        UIWindow *window;
        UINavigationController *navigationController;
        JourneyController *jList;
        //this is to hold the list of journey
        NSMutableArray *journeyList;
    }

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic, retain) NSMutableArray *journeyList;

-(void) copyDatabaseIfNeeded;
-(NSString *)getDBPath;

-(void)removeJourney:(NewJourney *)journeyobj;
-(void)addJourney:(NewJourney *)journeyobj;
@end

.m文件

#import "SqltestAppDelegate.h"
#import "JourneyController.h"
#import "NewJourney.h"

@implementation SqltestAppDelegate

@synthesize window;
@synthesize navigationController;
@synthesize journeyList;


#pragma mark -
#pragma mark Application lifecycle

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after application launch.
    //this function is used to copy database to user's phone if needed.
    [self copyDatabaseIfNeeded];
    //Initializing the journeylist array.
    NSMutableArray *tempArray = [[NSMutableArray alloc]init];
    self.journeyList = tempArray;
    [tempArray release];

    //this is function is used when once the db is copied, get the initial data to display on screen.
    [NewJourney getInitialDataToDisplay:[self getDBPath]];

    //configuring and displaying the window
    jList = [[JourneyController alloc]initWithNibName:@"JourneyController" bundle:nil];
    self.navigationController = [[[UINavigationController alloc]initWithRootViewController:jList]autorelease];
    [window addSubview:self.navigationController.view]; 
    [window makeKeyAndVisible];


}





- (void)applicationWillTerminate:(UIApplication *)application {

    [self.journeyList makeObjectsPerformSelector:@selector(saveAllData)];
    [NewJourney finalizeStatements];
}


#pragma mark -
#pragma mark Memory management

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {

    [self.journeyList makeObjectsPerformSelector:@selector(saveAllData)];

}


- (void)dealloc {
    [journeyList release];
    [navigationController release];
    [window release];
    [super dealloc];
}


- (void) copyDatabaseIfNeeded {

    //Using NSFileManager we can perform many file system operations.
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSString *dbPath = [self getDBPath];
    NSLog(@"%@",dbPath);
    BOOL success = [fileManager fileExistsAtPath:dbPath]; 

    if(!success) {

        NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"journey.sqlite"];
        success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];

        if (!success) 
            NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
    }   
}

- (NSString *) getDBPath {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
    NSString *documentsDir = [paths objectAtIndex:0];
    return [documentsDir stringByAppendingPathComponent:@"journey.sqlite"];
}

- (void)removeJourney:(NewJourney *)journeyobj {

    [journeyobj deleteCoffee];

    [journeyList removeObject:journeyobj];
}

- (void)addJourney:(NewJourney *)journeyobj {

    [journeyobj addCoffee];

    [journeyList addObject:journeyobj];
}



@end

这是我的新旅程课

#import <UIKit/UIKit.h>
#import <sqlite3.h>

@interface NewJourney : NSObject 
{
    NSInteger journeyID;
    NSString *journeyName;
    NSString *locationName;
    NSString *description;

    BOOL isDirty;
    BOOL isDetailViewHydrated;

}

@property(nonatomic, readonly)NSInteger journeyID;
@property(nonatomic, copy) NSString  *journeyName;
@property(nonatomic,copy) NSString *locationName;
@property(nonatomic,copy) NSString *description;

@property(nonatomic,readwrite) BOOL isDirty;
@property(nonatomic,readwrite) BOOL isDetailViewHydrated;

+(void) getInitialDataToDisplay:(NSString*)dbPath;
+(void) finalizeStatements;

-(id) initWithPrimaryKey:(NSInteger)pk;
-(void)deleteCoffee;
-(void)addCoffee;
//-(void)hydrateDetailViewData;
-(void)saveAllData;

@end

.M

#import "NewJourney.h"
#import "SqltestAppDelegate.h"
static sqlite3 *database = nil;
static sqlite3_stmt *deleteStmt = nil;
static sqlite3_stmt *addStmt = nil;
static sqlite3_stmt *detailSmt = nil;
static sqlite3_stmt *updateStmt = nil;

@implementation NewJourney
@synthesize journeyID,journeyName,locationName,description,isDirty,isDetailViewHydrated;

+(void) getInitialDataToDisplay:(NSString *)dbPath
{
    SqltestAppDelegate *appDelegate =(SqltestAppDelegate *)[[UIApplication sharedApplication]delegate];

    if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
    {
        const char *sql = "select JourneyID,JourneyName,LocationName,Description from UserJourney";
        sqlite3_stmt *selectstmt;
        if (sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
        {
            while (sqlite3_step(selectstmt) == SQLITE_ROW)
            {
                NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
                NewJourney *newobj = [[NewJourney alloc]initWithPrimaryKey:primaryKey];
                newobj.journeyName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
                newobj.isDirty = NO;
                [appDelegate.journeyList addObject:newobj];
                //[appDelegate.journeyList release];
                [newobj release];
            }
        }
    }
    else {
        sqlite3_close(database);
    }

}


+(void) finalizeStatements
{
    if (database) sqlite3_close(database);
    if (database) sqlite3_finalize(deleteStmt);
    if (database) sqlite3_finalize(addStmt);
    if (database) sqlite3_finalize(detailSmt);
    if (database) sqlite3_finalize(updateStmt);
}

-(id) initWithPrimaryKey:(NSInteger)pk
{
    [super init];
    journeyID = pk;
    isDetailViewHydrated = NO;
    return self;
}

-(void) deleteCoffee
{
    if (deleteStmt == nil)
    {
        const char *sql = "delete from UserJourney where JourneyID = ?";
        if (sqlite3_prepare_v2(database, sql, -1, &deleteStmt,NULL) != SQLITE_OK)
        {
            NSAssert1(0,@"Error while creating delete statemnet.'%s'",sqlite3_errmsg(database));
        }
        //when binding parameters, index starts from 1 and not zero.
        sqlite3_bind_int(deleteStmt, 1, journeyID);

        if (SQLITE_DONE != sqlite3_step(deleteStmt))
        {
            NSAssert1(0,@"Error while deleting. '%s'",sqlite3_errmsg(database));

        }
        sqlite3_reset(deleteStmt);
    }
}

-(void) addCoffee
{

    if (addStmt == nil)
    {
        const char *sql = "insert into UserJourney(JourneyName,LocationName,Description) Values(?,?,?)";
        if (sqlite3_prepare_v2(database, sql, -1,&addStmt , NULL) != SQLITE_OK)
        {
            NSAssert1(0,@"Error while creating add statement.'%s'",sqlite3_errmsg(database));
        }
        sqlite3_bind_text(addStmt, 1 , [journeyName UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(addStmt, 2 , [locationName UTF8String],-1, SQLITE_TRANSIENT);
        sqlite3_bind_text(addStmt, 3, [description UTF8String],-1, SQLITE_TRANSIENT);
        if (SQLITE_DONE != sqlite3_step(addStmt))
        {
            NSAssert1(0,@"Error while inserting data. '%s'",sqlite3_errmsg(database));
        }else
        {
            journeyID = sqlite3_last_insert_rowid(database);
        }
        sqlite3_reset(addStmt);
    }
}


-(void)saveAllData
{
    if (isDirty) {
        if (updateStmt == nil) {
            const char *sql = "update UserJourney Set JourneyName = ?,LocationName = ?,Description = ? Where JourneyID =?";
            if (sqlite3_prepare_v2(database, sql, -1, &updateStmt, NULL) != SQLITE_OK)
                NSAssert1(0,@"Error while creating update statement. '%s'",sqlite3_errmsg(database));

        }
        sqlite3_bind_text(updateStmt, 1, [journeyName UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(updateStmt, 2, [locationName UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(updateStmt, 3, [description UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_int(updateStmt,4, journeyID);

        if(SQLITE_DONE != sqlite3_step(updateStmt))
            NSAssert1(0, @"Error while updating. '%s'", sqlite3_errmsg(database));

        sqlite3_reset(updateStmt);

        isDirty = NO;

    }
    [journeyName release];
    //this is to test whether it will work or not.
    [locationName release];
    [description release];
    journeyName = nil;
    //this is to test .
    locationName = nil;
    description = nil;
    isDetailViewHydrated = NO;

}

- (void)setJourneyName:(NSString *)newName {

    self.isDirty = YES;
    [journeyName release];
    journeyName= [newName copy];
}

- (void)setLocationName:(NSString *)newLocation {

    self.isDirty = YES;
    [locationName release];
    locationName = [newLocation copy];
}

- (void)setDescription:(NSString *)newDescription {

    self.isDirty = YES;
    [description release];
    description = [newDescription copy];
}
- (void) dealloc {

    [journeyName release];
    [locationName release];
    [description release];
    [super dealloc];
}


@end

这是我的JourneyController类

#import <UIKit/UIKit.h>
@class NewJourney,AddController;
@class SqltestAppDelegate;


@interface JourneyController : UITableViewController 
{
    SqltestAppDelegate *appDelegate;
    AddController *addController;
    UINavigationController *addNavigationController;
}

@end

.M

#import "JourneyController.h"
#import "NewJourney.h"
#import "AddController.h"
#import "SqltestAppDelegate.h"


@implementation JourneyController


#pragma mark -
#pragma mark View lifecycle


- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.rightBarButtonItem = self.editButtonItem;
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(add_Clicked:)];
    appDelegate = (SqltestAppDelegate *)[[UIApplication sharedApplication] delegate];
    self.title = @"Journey List";

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return [appDelegate.journeyList count];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]autorelease];
    }

    //Get the object from the array.
    NewJourney *newobj = [appDelegate.journeyList objectAtIndex:indexPath.row];

    //Set the journeyname.
    cell.textLabel.text = newobj.journeyName;

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    // Configure the cell...

    return cell;
}



// Override to support editing the table view.
- (void)tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source.
        ///this is the code to get the object to delete  from array.
        NewJourney *newobj = [appDelegate.journeyList objectAtIndex:indexPath.row];
        [appDelegate removeJourney:newobj];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   

}


- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.tableView reloadData];
}

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {

    [super setEditing:editing animated:animated];
    [self.tableView setEditing:editing animated:YES];

    //Do not let the user add if the app is in edit mode.
    if(editing)
        self.navigationItem.leftBarButtonItem.enabled = NO;
    else
        self.navigationItem.leftBarButtonItem.enabled = YES;
}   


- (void) add_Clicked:(id)sender {

    if(addController == nil)
        addController = [[AddController alloc] initWithNibName:@"AddNew" bundle:nil];

    if(addNavigationController == nil)
        addNavigationController = [[UINavigationController alloc] initWithRootViewController:addController];

    [self.navigationController presentModalViewController:addNavigationController animated:YES];
}



#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     [detailViewController release];
     */
}


#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Relinquish ownership any cached data, images, etc. that aren't in use.
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}


- (void)dealloc {
    [addController release];
    [addNavigationController release];
    [super dealloc];
}


@end

这是我的addcontroller类

#import <UIKit/UIKit.h>

@class NewJourney;

@interface AddController : UIViewController {

    IBOutlet UITextField *txtJourneyName;
    IBOutlet UITextField *txtLocationName;
    IBOutlet UITextField *txtDescription;
}

@end

.M

#import "AddController.h"
#import "NewJourney.h"
#import "SqltestAppDelegate.h"

@implementation AddController

// Implement viewDidLoad to do additional setup after loading the view.
- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = @"Add Coffee";

    self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] 
                                              initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 
                                              target:self action:@selector(cancel_Clicked:)] autorelease];

    self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] 
                                               initWithBarButtonSystemItem:UIBarButtonSystemItemSave 
                                               target:self action:@selector(save_Clicked:)] autorelease];

    self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];
}


- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    //Set the textboxes to empty string.
    txtJourneyName.text = @"";
    txtLocationName.text = @"";
    txtDescription.text = @"";

    //Make the coffe name textfield to be the first responder.
    [txtJourneyName becomeFirstResponder];
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

- (void) save_Clicked:(id)sender {

    SqltestAppDelegate *appDelegate = (SqltestAppDelegate *)[[UIApplication sharedApplication] delegate];

    //Create a Coffee Object.
    NewJourney *coffeeObj = [[NewJourney alloc] initWithPrimaryKey:0];
    coffeeObj.journeyName = txtJourneyName.text;
    //NSDecimalNumber *temp = [[NSDecimalNumber alloc] initWithString:txtPrice.text];
    //coffeeObj.price = temp;
    //[temp release];
    coffeeObj.isDirty = NO;
    coffeeObj.isDetailViewHydrated = YES;

    //Add the object
    [appDelegate addJourney:coffeeObj];

    //Dismiss the controller.
    [self.navigationController dismissModalViewControllerAnimated:YES];
}

- (void) cancel_Clicked:(id)sender {

    //Dismiss the controller.
    [self.navigationController dismissModalViewControllerAnimated:YES];
}

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {

    [theTextField resignFirstResponder];
    return YES;
}

- (void)dealloc {
    [txtJourneyName release];
    [txtLocationName release];
    [txtDescription release];
    [super dealloc];
}


@end
答案

addCoffee中的代码只运行一次,因为一旦你创建了addStmt,下次执行该方法时,if语句会导致整个代码被省略,包括实际插入。


另外,在关闭数据库之前,必须完成sqlite3语句的最终确定。

以上是关于在数据库中一次添加2行或3行无法在iPhone中添加记录的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Mac OS X 命令行或脚本可靠地响铃我的 iPhone?

如何将 2 行或更多行的数据添加到 postgresql 中的一行

如何在R中一次按两列对行进行排名?

从iPhone的核心数据在tableview中一一添加单行

如何从输入文件中一次读取两行并将它们添加到对象中?

无法在命令行或管理仪表板中创建 AWS Elastic Beanstalk 环境