使用 FMDB 和 Obj-C 换行
Line breaks using FMDB and Obj-C
我对 iOS 编程比较陌生,所以请多多包涵。
我正在创建一个从 table 视图调用食谱的应用程序,然后在详细视图中将测量值和成分列为标签。我在 Google 表格中对我的食谱进行了分类,将其下载为 .csv 文件并使用 SQLiteStudio 填充了 table。然后我导出数据库,并使用 FMDB 将其放入我的应用程序中。那里一切正常,我能够检索各种字段。
我想做的是列出尺寸和成分,以便显示时换行:
0.5 oz.
1.0 oz.
1 jigger
而不是:0.5 oz., 1.0 oz., 1 jigger
这就是我将其写入 Google 文档的方式。
我曾尝试在 SQLite 查看器中使用 \n
,但它会将其输出为字符串而不是将其编码为新行。但是,当我查看随附的 .sql 文件时,TextMate2 将其作为新行读取。我不确定是否必须在调用 FMDB 的 tableviewcontroller 实现文件中或其他地方应用一些代码。
我一直在寻找解决方案,但一直没有成功。任何帮助我朝着正确方向前进的帮助将不胜感激。谢谢!
CocktailListTableViewController.m
- (NSMutableArray *)recipeCocktails {
recipeCocktails = [[NSMutableArray alloc] init];
NSString *databasePath = [(AppDelegate *) [[UIApplication sharedApplication] delegate] databasePath];
FMDatabase *fmDB = [FMDatabase databaseWithPath:databasePath];
if(![fmDB open])
{
NSLog(@"Could not open DB, try again");
return nil;
}
FMResultSet *results = nil;
results = [fmDB executeQuery:@"SELECT * FROM recipesCocktails"];
NSLog(@"result %@ ",results);
if ([fmDB hadError]) {
NSLog(@"DB Error %d: %@", [fmDB lastErrorCode], [fmDB lastErrorMessage]);
}
while ([results next]) {
Cocktails *cocktails = [[Cocktails alloc] init];
cocktails.recipeName = [results stringForColumn:@"recipeName"];
cocktails.recipeMeasure = [results stringForColumn:@"recipeMeasure"];
cocktails.recipeIngred = [results stringForColumn:@"recipeIngred"];
cocktails.recipeGlass = [results stringForColumn:@"recipeGlass"];
cocktails.recipeShaker = [results stringForColumn:@"recipeShaker"];
cocktails.recipeDirections = [results stringForColumn:@"recipeDirections"];
[recipeCocktails addObject:cocktails];
}
[fmDB close];
return recipeCocktails;
CocktailsDetailTableViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = cocktails.recipeName;
self.recipeIngred.text = cocktails.recipeIngred;
self.recipeMeasure.text = cocktails.recipeMeasure;
这个问题有两种解决方法。
一种方法是将成分列表存储为单个文本字段,在字符串中使用换行符。 SQLite(和 FMDB)处理得很好。
从 UI 的角度来看,您将以多行 UITextField
或 UILabel
的形式显示此文本字段。如果您使用 UILabel
,请确保将行数设置为 1 以外的值(即零或实际行数)。
现在这里的技巧是将这个换行字符串输入数据库。这取决于你是如何做的。但是如果你使用一些 SQLite 工具,你不能使用 \n
序列,因为那不是 acceptable SQL 语法。您可以使用 x'0a'
或 char(10)
:
insert into foo (bar) values ('baz' || x'0a' || 'qux');
或:
insert into foo (bar) values ('baz' || char(10) || 'qux');
或者,如果使用 SQLite 命令行工具,您可以只插入换行符:
insert into foo (bar) values ('baz
qux');
但是你不能使用\n
序列。您可以通过 Objective-C 代码执行此操作,但不能通过第三方 SQLite 工具执行此操作。
另一种方法是将食谱列表和每个食谱的配料列表存储在两个不同的 table 中(例如 recipes
和 ingredients
).然后,您可以将每种成分存储在 ingredients
table.
中的单独行中
我觉得这是一个更合乎逻辑的实现。如果你这样做,你就可以选择如何显示成分列表(单独的 UILabel
控件,一个 UITableView
,或者,如果你真的想要,将它们连接在一起,用换行符分隔并在单个多行控件中显示它们。
我看到您正在尝试将所有成分存储为一个长的、预先构建的字符串,我认为这种方法不是最好的。
它会起作用,但它不是面向未来的,或者只是......通常。
我强烈建议有一个新的 table,它知道所有可能的成分,带有 ID 和您意愿的其他信息(颜色、平均重量、图片* 等等)
( 请注意,不建议将图像存储在 SQL 数据库中,您更愿意将引用存储到将它们保存为文件的位置或 URL的)*
一旦你拥有 table,你就是黄金。您只需在食谱中引用一系列成分 table。例如 [1,27,133]
,这样你就可以做你想做的事了。您有一组成分对象,您可以根据自己的喜好进行处理。
例如,我会在它上面循环并在彼此下面创建标签,这样你就有了你的台词。
我也可以简单地使用 NSMutableString 并用 ingredients.name 填充它(再次使用示例)
您可以在每个成分之间用换行符填充 UITextView(通过使用 NSMutableString 并在每个对象名称之间添加换行符)。
更重要的是,您可以修改所有内容,而无需重新设计布局或标签或重新编写整个数据库,因为每个食谱都有静态换行成分。
这是我想表达的最重要的一点。使用这种方法,您可以从任何食谱中删除任何成分,而不必考虑太多或冒忘记某些事情的风险。您还可以通过将其从成分 table 中移除来永久销毁每个食谱的任何成分。添加新的也一样。或者说您想更改成分 X 的名称,您不必在每个食谱中都这样做,等等。
编辑:在评论中回答您的问题
要在 table 视图中加载食谱并在详细信息页面中加载成分,您可以这样做:
您将所有食谱加载到一个数组中并显示(我认为您已经在这方面取得了成功)。
请注意,所有食谱都有一个名为 "Ingredients" 的 属性,它是一个成分数组 keys/ids/something
在单元格点击时,您想加载您只知道其 ID 的成分,您只需从存储在食谱中的 ID 数组中获取它们,然后 SELECT他们来自你的数据库。
在全球范围内,在用户点击之前您不知道成分是什么:如果您不需要在 table 视图中显示它们,那么您还不需要加载它们。但是你已经知道他们的id了(否则你就找不到他们了!)。
我对 iOS 编程比较陌生,所以请多多包涵。
我正在创建一个从 table 视图调用食谱的应用程序,然后在详细视图中将测量值和成分列为标签。我在 Google 表格中对我的食谱进行了分类,将其下载为 .csv 文件并使用 SQLiteStudio 填充了 table。然后我导出数据库,并使用 FMDB 将其放入我的应用程序中。那里一切正常,我能够检索各种字段。
我想做的是列出尺寸和成分,以便显示时换行:
0.5 oz.
1.0 oz.
1 jigger
而不是:0.5 oz., 1.0 oz., 1 jigger
这就是我将其写入 Google 文档的方式。
我曾尝试在 SQLite 查看器中使用 \n
,但它会将其输出为字符串而不是将其编码为新行。但是,当我查看随附的 .sql 文件时,TextMate2 将其作为新行读取。我不确定是否必须在调用 FMDB 的 tableviewcontroller 实现文件中或其他地方应用一些代码。
我一直在寻找解决方案,但一直没有成功。任何帮助我朝着正确方向前进的帮助将不胜感激。谢谢!
CocktailListTableViewController.m
- (NSMutableArray *)recipeCocktails {
recipeCocktails = [[NSMutableArray alloc] init];
NSString *databasePath = [(AppDelegate *) [[UIApplication sharedApplication] delegate] databasePath];
FMDatabase *fmDB = [FMDatabase databaseWithPath:databasePath];
if(![fmDB open])
{
NSLog(@"Could not open DB, try again");
return nil;
}
FMResultSet *results = nil;
results = [fmDB executeQuery:@"SELECT * FROM recipesCocktails"];
NSLog(@"result %@ ",results);
if ([fmDB hadError]) {
NSLog(@"DB Error %d: %@", [fmDB lastErrorCode], [fmDB lastErrorMessage]);
}
while ([results next]) {
Cocktails *cocktails = [[Cocktails alloc] init];
cocktails.recipeName = [results stringForColumn:@"recipeName"];
cocktails.recipeMeasure = [results stringForColumn:@"recipeMeasure"];
cocktails.recipeIngred = [results stringForColumn:@"recipeIngred"];
cocktails.recipeGlass = [results stringForColumn:@"recipeGlass"];
cocktails.recipeShaker = [results stringForColumn:@"recipeShaker"];
cocktails.recipeDirections = [results stringForColumn:@"recipeDirections"];
[recipeCocktails addObject:cocktails];
}
[fmDB close];
return recipeCocktails;
CocktailsDetailTableViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = cocktails.recipeName;
self.recipeIngred.text = cocktails.recipeIngred;
self.recipeMeasure.text = cocktails.recipeMeasure;
这个问题有两种解决方法。
一种方法是将成分列表存储为单个文本字段,在字符串中使用换行符。 SQLite(和 FMDB)处理得很好。
从 UI 的角度来看,您将以多行
UITextField
或UILabel
的形式显示此文本字段。如果您使用UILabel
,请确保将行数设置为 1 以外的值(即零或实际行数)。现在这里的技巧是将这个换行字符串输入数据库。这取决于你是如何做的。但是如果你使用一些 SQLite 工具,你不能使用
\n
序列,因为那不是 acceptable SQL 语法。您可以使用x'0a'
或char(10)
:insert into foo (bar) values ('baz' || x'0a' || 'qux');
或:
insert into foo (bar) values ('baz' || char(10) || 'qux');
或者,如果使用 SQLite 命令行工具,您可以只插入换行符:
insert into foo (bar) values ('baz qux');
但是你不能使用
\n
序列。您可以通过 Objective-C 代码执行此操作,但不能通过第三方 SQLite 工具执行此操作。另一种方法是将食谱列表和每个食谱的配料列表存储在两个不同的 table 中(例如
中的单独行中recipes
和ingredients
).然后,您可以将每种成分存储在ingredients
table.我觉得这是一个更合乎逻辑的实现。如果你这样做,你就可以选择如何显示成分列表(单独的
UILabel
控件,一个UITableView
,或者,如果你真的想要,将它们连接在一起,用换行符分隔并在单个多行控件中显示它们。
我看到您正在尝试将所有成分存储为一个长的、预先构建的字符串,我认为这种方法不是最好的。
它会起作用,但它不是面向未来的,或者只是......通常。
我强烈建议有一个新的 table,它知道所有可能的成分,带有 ID 和您意愿的其他信息(颜色、平均重量、图片* 等等)
( 请注意,不建议将图像存储在 SQL 数据库中,您更愿意将引用存储到将它们保存为文件的位置或 URL的)*
一旦你拥有 table,你就是黄金。您只需在食谱中引用一系列成分 table。例如 [1,27,133]
,这样你就可以做你想做的事了。您有一组成分对象,您可以根据自己的喜好进行处理。
例如,我会在它上面循环并在彼此下面创建标签,这样你就有了你的台词。 我也可以简单地使用 NSMutableString 并用 ingredients.name 填充它(再次使用示例) 您可以在每个成分之间用换行符填充 UITextView(通过使用 NSMutableString 并在每个对象名称之间添加换行符)。
更重要的是,您可以修改所有内容,而无需重新设计布局或标签或重新编写整个数据库,因为每个食谱都有静态换行成分。
这是我想表达的最重要的一点。使用这种方法,您可以从任何食谱中删除任何成分,而不必考虑太多或冒忘记某些事情的风险。您还可以通过将其从成分 table 中移除来永久销毁每个食谱的任何成分。添加新的也一样。或者说您想更改成分 X 的名称,您不必在每个食谱中都这样做,等等。
编辑:在评论中回答您的问题
要在 table 视图中加载食谱并在详细信息页面中加载成分,您可以这样做:
您将所有食谱加载到一个数组中并显示(我认为您已经在这方面取得了成功)。 请注意,所有食谱都有一个名为 "Ingredients" 的 属性,它是一个成分数组 keys/ids/something
在单元格点击时,您想加载您只知道其 ID 的成分,您只需从存储在食谱中的 ID 数组中获取它们,然后 SELECT他们来自你的数据库。
在全球范围内,在用户点击之前您不知道成分是什么:如果您不需要在 table 视图中显示它们,那么您还不需要加载它们。但是你已经知道他们的id了(否则你就找不到他们了!)。