0

首先我想明确一点,在这种情况下我不想使用 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),没有别的。下面的视图是指示崩溃发生位置的组装说明。但是,我现在不知道如何解释它们。

在此处输入图像描述

我的问题:为什么会发生这种崩溃?

谢谢你的帮助。

4

0 回答 0