如何使用Sqlite管理iPhone上对象的数据库关系

时间:2009-06-16 22:31:00

标签: iphone sqlite uitableview

例如,如果我能够显示包含所有电影和流派的UITableView。单击电影上的编辑应该加载一个新视图(这是正确的方式,加载编辑视图吗?)与文本框和某种选择器或其他视图来选择类型。选择类型后,如何捕获GenreId以保存在电影表中?

CREATE TABLE movie(pk INTEGER PRIMARY KEY, title TEXT, genreId INTEGER);

INSERT INTO make(title) VALUES('GoldFinger', 1);
INSERT INTO make(title) VALUES('Octopussy', 1);
INSERT INTO make(title) VALUES('Love Story', 3);
INSERT INTO make(title) VALUES('Where Eagles Dare', 1);
INSERT INTO make(title) VALUES('Zombies', 2);

CREATE TABLE genre(pk INTEGER PRIMARY KEY, title TEXT);

INSERT INTO genre(title) VALUES('Thriller');
INSERT INTO genre(title) VALUES('Horror');
INSERT INTO genre(title) VALUES('Romance');

我使用的是Sqlitebooks样本作为指南。

// Movie.h
@interface Movie : NSObject {
// Opaque reference to the underlying database.
sqlite3 *database;
// Primary key in the database.
NSInteger primaryKey;
// Attributes.
NSString *title;
NSInteger *genreKey;
// Internal state variables. Hydrated tracks whether attribute data is in the object or the database.
BOOL hydrated;
// Dirty tracks whether there are in-memory changes to data which have no been written to the database.
BOOL dirty;
NSData *data;
}
// Property exposure for primary key and other attributes. The primary key is 'assign'     because it is not an object,
// nonatomic because there is no need for concurrent access, and readonly because it     cannot be changed without
// corrupting the database.
@property (assign, nonatomic, readonly) NSInteger primaryKey;
// The remaining attributes are copied rather than retained because they are value     objects.
@property (copy, nonatomic) NSString *title;
@property (copy, nonatomic) NSInteger *genreKey;
// Finalize (delete) all of the SQLite compiled queries.
+ (void)finalizeStatements;
// Creates the object with primary key and title is brought into memory.
- (id)initWithPrimaryKey:(NSInteger)pk database:(sqlite3 *)db;
// Inserts the book into the database and stores its primary key.
- (void)insertIntoDatabase:(sqlite3 *)database;
// Brings the rest of the object data into memory. If already in memory, no action is     taken (harmless no-op).
- (void)hydrate;
// Flushes all but the primary key and title out to the database.
- (void)dehydrate;
// Remove the book complete from the database. In memory deletion to follow...
- (void)deleteFromDatabase;

// Movie.m
// Flushes all but the primary key and title out to the database.
- (void)dehydrate {
    if (dirty) {
    // Write any changes to the database.
    // First, if needed, compile the dehydrate query.
    if (dehydrate_statement == nil) {
        const char *sql = "UPDATE movie SET title=?, genreid=? WHERE pk=?";
        if (sqlite3_prepare_v2(database, sql, -1, &dehydrate_statement, NULL) != SQLITE_OK) {
            NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
        }
    }
    // Bind the query variables.
    sqlite3_bind_text(dehydrate_statement, 1, [title UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(dehydrate_statement, 2, [genreId UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_int(dehydrate_statement, 3, primaryKey);
    // Execute the query.
    int success = sqlite3_step(dehydrate_statement);
    // Reset the query for the next use.
    sqlite3_reset(dehydrate_statement);
    // Handle errors.
    if (success != SQLITE_DONE) {
        NSAssert1(0, @"Error: failed to dehydrate with message '%s'.", sqlite3_errmsg(database));
    }
    // Update the object state with respect to unwritten changes.
    dirty = NO;
}
// Release member variables to reclaim memory. Set to nil to avoid over-releasing them 
// if dehydrate is called multiple times.
[movie release];
movie = nil;
[data release];
data = nil;
// Update the object state with respect to hydration.
hydrated = NO;
}
@end

1 个答案:

答案 0 :(得分:2)

这并不直接回答您的问题,但是,我建议您查看3.0 SDK中添加的新CoreData API。它们将允许您对关系数据建模并抽象出任何手动SQL工作,从而允许更少的代码,如果正确完成,可以获得更好的性能。