首先我想明确一点,在这种情况下我不想使用 Core Data。
我的问题:每当我的 tableview 的委托方法numberOfRowsInSection
被调用时,应用程序就会崩溃,只显示一条(lldb)
错误消息。
首先,我有两个类可以帮助我从 SQLite 数据库中检索行。
sqlite.m:
#import "sqlite.h"
#import <sqlite3.h>
@implementation sqlite
@synthesize carbohydrates = _carbohydrates;
@synthesize name = _name;
@synthesize fat = _fat;
@synthesize kcal = _kcal;
- (id)initWithName:(NSString *)name2 carbs:(NSNumber *)carbs2
fat:(NSNumber *)fat2 kcal:(NSNumber*)kcal2 {
if ((self = [super init])) {
self.carbohydrates = carbs2;
self.name = name2;
self.fat = fat2;
self.kcal = kcal2;
}
return self;
}
- (void) dealloc {
self.name = nil;
self.kcal = nil;
self.fat = nil;
self.carbohydrates = nil;
[super dealloc];
}
@end
营养数据库.m:
#import "NutritionsDB.h"
#import "sqlite.h"
@implementation NutritionsDB
static NutritionsDB *_database;
+ (NutritionsDB*)database {
if (_database == nil) {
_database = [[NutritionsDB alloc] init];
}
return _database;
}
- (id)init {
if ((self = [super init])) {
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:@"Livsmedeldatabas"
ofType:@"sqlite"];
if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) {
NSLog(@"Failed to open database!");
}
}
return self;
}
- (void)dealloc {
sqlite3_close(_database);
[super dealloc];
}
-(void)setUpDB{
const char *sql_stmt = "CREATE INDEX IF NOT EXISTS name_index on livsmedel(namn)";
char *errMsg;
if (sqlite3_exec(_database, sql_stmt, NULL, NULL, &errMsg) == SQLITE_OK)
{
puts("Index successfully created");
// SQL statement execution succeeded
}
}
-(NSArray*)sqliteInfo:(NSString*)predicateString{
NSMutableArray *retval = [[[NSMutableArray alloc] init] autorelease];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [predicateString cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameChars = (char *) sqlite3_column_text(statement, 0);
char *kcalchars = (char *) sqlite3_column_text(statement, 1);
char *fatchars = (char *) sqlite3_column_text(statement, 2);
char *carbchars = (char *) sqlite3_column_text(statement, 3);
NSLog(@"\n%s, \n%s, \n%s", kcalchars, fatchars, carbchars);
NSString *name = [[NSString alloc] initWithUTF8String:nameChars];
NSString *kcal = [NSString stringWithFormat:@"%s", kcalchars];
NSString *fat = [NSString stringWithFormat:@"%s", fatchars];
NSString *carb = [NSString stringWithFormat:@"%s", carbchars];
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * kcalNumber = [f numberFromString:kcal];
NSNumber * fatNumber = [f numberFromString:fat];
NSNumber * carbNumber = [f numberFromString:carb];
NSLog(@"\n kcalnum : %@, \n fatnum: %@, \n carbnum : %@", kcalNumber, fatNumber, carbNumber);
[f release];
sqlite *info = [[sqlite alloc] initWithName:name carbs:carbNumber fat:fatNumber kcal:kcalNumber] ;
NSLog(@"%@,%@,%@,%@", name, kcal, fat, carb);
[retval addObject:info];
[name release];
[kcal release];
[fat release];
[carb release];
}
sqlite3_finalize(statement);
}
return retval;
}
@end
现在,在我的一个视图控制器中,我不断地通过该方法进行数据库调用
-(NSArray*)sqliteInfo:(NSString*)predicateString
.
predicateString
是用户在 VC 内的搜索栏中输入的文本的副本。
除了 之外UISearchBar
,VC 还持有 aUITableView
来表示从数据库中获取的行。
这是我更新数据源内容并重新呈现表格视图的方法。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.nutritionList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"hej");
static NSString *CellIdentifier = @"NutritionIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.font = [UIFont fontWithName:@"Avenir-Medium" size:18.0];
cell.textLabel.text = [(sqlite*)[self.nutritionList objectAtIndex:indexPath.row] name];
return cell;
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[self.nutritionList removeAllObjects];
if (searchText.length < 2) {
;
} else {
NSString *firstChar = [searchText substringWithRange:NSMakeRange(0, 1)];
if([firstChar isEqualToString:@"å"] ||
[firstChar isEqualToString:@"Å"] ||
[firstChar isEqualToString:@"ä"] ||
[firstChar isEqualToString:@"Ä"] ||
[firstChar isEqualToString:@"ö"] ||
[firstChar isEqualToString:@"Ö"]){
NSString *lowerString = [firstChar lowercaseString];
NSString *upperString = [firstChar uppercaseString];
NSString *newSearchText = [searchText stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:lowerString];
NSString *newSearchText_upper = [searchText stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:upperString];
NSString *formatString = [[[[[@"'"stringByAppendingString:newSearchText]stringByAppendingString:@"%'"]
stringByAppendingString:@" OR namn like'"]stringByAppendingString:newSearchText_upper]stringByAppendingString:@"%' ORDER BY namn COLLATE NOCASE"];
NSArray *array = [[NutritionsDB database] sqliteInfo:[NSString stringWithFormat:@"Select * from livsmedel where namn like %@", formatString ]];
NSLog(@"%@",[NSString stringWithFormat:@"Select * from livsmedel where namn like %@", formatString ] );
for (sqlite *info in array) {
[self.nutritionList addObject:info];
}
}else{
NSString *formatString = [[@"'"stringByAppendingString:searchText]stringByAppendingString:@"%' "];
NSArray *array = [[NutritionsDB database] sqliteInfo:[NSString stringWithFormat:@"SELECT * FROM livsmedel WHERE namn LIKE %@", formatString ]];
NSLog(@"%@",[NSString stringWithFormat:@"Select * from livsmedel where namn like %@", formatString ] );
for (sqlite *info in array) {
[self.nutritionList addObject:info];
NSLog(@"carbs %@, fat %@, kcal %@", info.carbohydrates, info.fat, info.kcal);
}
}
}
[self.tableView reloadData];
}
最后崩溃发生在numberOfRowsInSection方法被调用之后,但在 cellForRowAtIndexPath 被调用之前。他们之间的某个地方。
控制台说(lldb)
,没有别的。下面的视图是指示崩溃发生位置的组装说明。但是,我现在不知道如何解释它们。
我的问题:为什么会发生这种崩溃?
谢谢你的帮助。