如何为iOS的sqLite创建从上次插入到sqLite的json对象和数据库浏览器
我有两个主要问题 第一个;我在iOS应用程序中使用的sqlite是否有数据库浏览器 第二个问题——大问题——有点复杂如何为iOS的sqLite创建从上次插入到sqLite的json对象和数据库浏览器,ios,objective-c,json,sqlite,cocoa-touch,Ios,Objective C,Json,Sqlite,Cocoa Touch,我有两个主要问题 第一个;我在iOS应用程序中使用的sqlite是否有数据库浏览器 第二个问题——大问题——有点复杂 -(BOOL)createDB{ NSString *docsDir; NSArray *dirPaths; // Get the documents directory dirPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask
-(BOOL)createDB{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString:
[docsDir stringByAppendingPathComponent: @"insider.db"]];
BOOL isSuccess = YES;
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt =
"create table if not exists userInfo (device_token text primary key, device_type text, carrier text, app_version text,os_version text, first_name text, last_name text,last_viewed_item text, last_added_item text, last_item_price_tag text, name_entered integer, login_screen integer, item_detailed_screen integer )";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg)
!= SQLITE_OK)
{
isSuccess = NO;
NSLog(@"Failed to create table");
}
sqlite3_close(database);
return isSuccess;
}
else {
isSuccess = NO;
NSLog(@"Failed to open/create database");
}
}
return isSuccess;
}
这是我的createDB方法,我称之为我的applicationIDbecome active
我有几种方法来获取将被保存到数据库中的项目,其中之一
-(BOOL)getUserFirstName:(NSString *)firstName {
NSLog(@"User's first name is this %@",firstName);
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:@"insert into userInfo (first_name) values (\"%@\")", firstName];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
return YES;
}
else {
return NO;
}
sqlite3_reset(statement);
}
return NO;
}
我有很多这样的方法(对于CREATETABLE语句中的每一列)
我想要的是这个
我有一个后端使用mysql作为数据库
-(BOOL)insertUserFirstName:(NSString *)firstName
{
BOOL success = YES;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
const char *insert_stmt = "insert into userInfo (first_name) values (?)";
if (sqlite3_prepare_v2(database, insert_stmt, -1, &statement, NULL) != SQLITE_OK) {
NSLog(@"prepare failure: %s", sqlite3_errmsg(database));
sqlite3_close(database);
return NO;
}
if (sqlite3_bind_text(statement, 1, [firstName UTF8String], -1, NULL) != SQLITE_OK) {
success = NO;
NSLog(@"bind 1 failure: %s", sqlite3_errmsg(database));
} else if (sqlite3_step(statement) != SQLITE_DONE) {
success = NO;
NSLog(@"step failure: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
statement = NULL;
sqlite3_close(database);
database = NULL;
}
return success;
}
我需要创建最后一个插入行,并将其设置为JSON格式,以便可以对其进行操作并将其写入后端服务器
我该怎么做
提前谢谢
切里斯
~/Library/Application Support/iPhone simulator
,在Xcode 6中是~/Library/Developer/CoreSimulator/Devices
),然后打开数据库。如果您的Library
文件夹被隐藏,您可以从终端命令行chflags nohidden~/Library
取消隐藏它
您可以使用Mac OS Xsqlite3
命令行应用程序。许多人使用免费的Firefox SQLite Manager插件。我个人使用的是一个相对便宜的SQLite工具。你想用什么就用什么NSDictionary
,然后可以将其传递到NSJSONSerialization
方法dataWithJSONObject
,该方法可以构建请求的JSON主体
因此,假设您将有一些模型结构来捕获这个本地表的十三列中的内容。因此,在本地表中插入该数据,然后编写一个不同的例程,获取该模型数据并创建请求,将该数据发布到服务器
您需要确定web服务API的外观以及发布方式(例如,NSURLConnection
,NSURLSession
(适用于iOS 7及更高版本),但这似乎远远超出了此问题的范围sqlite3\u exec
,为错误消息提供指向char*
的指针,请记住,您负责释放该错误消息。此外,您还可以记录该错误消息,以便了解失败的原因:
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) {
isSuccess = NO;
NSLog(@"Failed to create table: %s", errMsg);
sqlite3_free(errMsg);
}
有关更多信息,请参阅sqlite3\u exec
stringWithFormat
来构建INSERT
语句。始终在SQL中使用?
占位符,然后手动绑定值
此外,如果语句成功,getUserFirstName
将立即返回。因此,它并没有释放与sqlite3\u prepare\u v2
相关的内存(您应该通过sqlite3\u finalize
,而不是sqlite3\u reset
)。它也没有关闭数据库
-(BOOL)insertUserFirstName:(NSString *)firstName
{
BOOL success = YES;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
const char *insert_stmt = "insert into userInfo (first_name) values (?)";
if (sqlite3_prepare_v2(database, insert_stmt, -1, &statement, NULL) != SQLITE_OK) {
NSLog(@"prepare failure: %s", sqlite3_errmsg(database));
sqlite3_close(database);
return NO;
}
if (sqlite3_bind_text(statement, 1, [firstName UTF8String], -1, NULL) != SQLITE_OK) {
success = NO;
NSLog(@"bind 1 failure: %s", sqlite3_errmsg(database));
} else if (sqlite3_step(statement) != SQLITE_DONE) {
success = NO;
NSLog(@"step failure: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
statement = NULL;
sqlite3_close(database);
database = NULL;
}
return success;
}
就个人而言,我甚至建议不要在每次SQLite调用时打开和关闭数据库。但如果你这样做了,确保你平衡了你的开放式陈述和封闭式陈述,如上文所述。您可能还想测试以确保firstName
不是nil
(如果是,则调用sqlite3\u bind\u null
,而不是sqlite3\u bind\u text
)编写SQLite代码时,您可能需要考虑使用SQLite C API周围的瘦Objto-C包装器,这大大简化了您的生活。当您处理第3步时,为十三列中的每一列执行
sqlite3\u bind\u XXX
调用,我想您将真正开始欣赏类似FMDB的功能如果这是您的第一个web服务项目,我可能建议您查看Wenderlich的和。后者使用了现在已经过时的ASIHTTPRequest(现在很多人更喜欢AFNetworking),但它可能仍然是对iOS应用程序和后端MySQL数据库之间交配仪式的一个很好的介绍。首先,老兄,我非常感谢你给出了这么长的答案。现在大多数用户只想快速获得+1票,但你老兄,你的目的当然是为了帮助op——在这个例子中是我——写你的笔记,是的,这将是我的第一次连接试用。是的,我将写所有13列,然后用json将其写入mysql,你能指出我正在做的更多错误点吗?例如,我不确定是否要删除我将发送到mysql的内容。我应该将它们保存在sqlite中吗?或者是否有任何系统会让我知道传递成功。再次非常感谢:)保存发送到服务器的内容的本地副本通常是合理的,以便在需要时要再次向用户显示它,您不必从服务器重新检索它。更重要的是,您希望编写web服务,以便在成功接收数据并将其存储在MySQL数据库中时提供确认。让web服务使用JSON响应可以使客户端应用程序更容易解析响应并确认成功。这并不是自动发生的:你必须自己编写web服务来提供成功的确认。你能告诉我关于这个sqlite包装器的情况吗,我应该在哪里使用它?另外,我的连接是片面的。我不会从服务器接收数据,我只会发送推送通知。当使用sqlite C界面时,很容易泄漏内存(如您的问题所示),而我