cocoatouch-tableView从详细视图iphone返回时崩溃



在我的应用程序中,我有一个表视图和一个详细信息视图。表视图是通过数据库查询填充的。我在viewDidLoad方法中有这个数据库方法(我不知道还能把它放在哪里)然后在viewWillAppear方法中有[self.tableView reload]方法。问题是,当我从详细信息视图返回到表视图并单击(表视图中的)同一元素时,应用程序会崩溃。我想这是因为当我从详细视图返回并单击单元格时,数据库方法仍在运行。因此,表视图中的数据永远不会被重新加载。你们知道怎么解决这个问题吗?

*编辑:*这是数据库中的代码,我用它来填充表视图:*

- (void)viewDidLoad
{
    //Convert the course id to string 
    NSString *selectedCategoryIdConverted = [NSString stringWithFormat:@"%d", self.selectedCategory._id];
    NSMutableArray *tempArray = [[NSMutableArray alloc]init];
    // Set up sqlite statement
    sqlite3_stmt *dbStatement = nil;
    NSString *sqlQuery = [NSString stringWithFormat:@"SELECT co.name, co.id, o.location FROM course as co JOIN categories as ca JOIN occasions as o WHERE co.catID = ca.id AND co.catID = %i AND o.courseID = co.id", self.selectedCategory._id];
    //Convert the query string to const char
    const char *sqlQueryConverted =[sqlQuery UTF8String];
    int prepareSqlQuery = sqlite3_prepare_v2( [[DatabaseController sharedDatabaseController] getDb], sqlQueryConverted, -1, &dbStatement, NULL);
    //Run the query
    while ( sqlite3_step(dbStatement) == SQLITE_ROW ) 
    {    
            const char *name = (const char *)sqlite3_column_text(dbStatement, 0);
            int courseId = sqlite3_column_int(dbStatement, 1);
            const char *location = (const char *)sqlite3_column_text(dbStatement, 2);
            //Convert the returnedElement char to string
            NSString *nameConverted = [[[NSString alloc] initWithUTF8String:name] autorelease];
            NSString *locationConverted = [[[NSString alloc] initWithUTF8String:location] autorelease];
            Course *course = [[Course alloc] initWithName:nameConverted _id:courseId location:locationConverted];

            [tempArray addObject:course];
    }    
    self.courses = tempArray;
    [super viewDidLoad];
   }

编辑:我注意到,当我返回到表视图时,如果我单击下一个元素,应用程序不会崩溃,但如果我单击表视图中的上一个元素(行),应用程序会崩溃。

编辑:我将代码更改为viewDidAppear方法并修复了内存泄漏。self.courses就是(nonatomic, retain)这是代码:

- (void)viewWillAppear:(BOOL)animated
{
    //Convert the course id to string 
    //NSString *selectedCategoryIdConverted = [NSString stringWithFormat:@"%d", self.selectedCategory._id];
    NSMutableArray *tempArray = [[NSMutableArray alloc]init];
    // Set up sqlite statement
    sqlite3_stmt *dbStatement = nil;
    NSString *sqlQuery = [NSString stringWithFormat:@"SELECT co.name, co.id, o.location FROM course as co JOIN categories as ca JOIN occasions as o WHERE co.catID = ca.id AND co.catID = %i AND o.courseID = co.id", self.selectedCategory._id];
    //Convert the query string to const char
    const char *sqlQueryConverted =[sqlQuery UTF8String];
    int prepareSqlQuery = sqlite3_prepare_v2( [[DatabaseController sharedDatabaseController] getDb], sqlQueryConverted, -1, &dbStatement, NULL);
    //Run the query
    while ( sqlite3_step(dbStatement) == SQLITE_ROW ) 
    {    
        const char *name = (const char *)sqlite3_column_text(dbStatement, 0);
        int courseId = sqlite3_column_int(dbStatement, 1);
        const char *location = (const char *)sqlite3_column_text(dbStatement, 2);
        //Convert the returnedElement char to string
        NSString *nameConverted = [[[NSString alloc] initWithUTF8String:name] autorelease];
        NSString *locationConverted = [[[NSString alloc] initWithUTF8String:location] autorelease];
        Course *course = [[Course alloc] initWithName:nameConverted _id:courseId location:locationConverted];

        [tempArray addObject:course];
        [course release];
        course = nil;
    }    
    self.courses = tempArray;
    [tempArray release];
    [self.tableView reloadData];    
    [super viewWillAppear:animated];
}

编辑:这是错误日志:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIDeviceWhiteColor _id]: unrecognized selector sent to instance 0x4d2e2a0'
Call stack at first throw:
(
    0   CoreFoundation                      0x010435a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x01197313 objc_exception_throw + 44
    2   CoreFoundation                      0x010450bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x00fb4966 ___forwarding___ + 966
    4   CoreFoundation                      0x00fb4522 _CF_forwarding_prep_0 + 50
    5   BookApp                             0x000079e8 -[CoursesCategoriesViewController viewWillAppear:] + 184
    6   UIKit                               0x0017c9be -[UINavigationController _startTransition:fromViewController:toViewController:] + 858
    7   UIKit                               0x0017732a -[UINavigationController _startDeferredTransitionIfNeeded] + 266
    8   UIKit                               0x0017e562 -[UINavigationController pushViewController:transition:forceImmediate:] + 932
    9   UIKit                               0x001771c4 -[UINavigationController pushViewController:animated:] + 62
    10  BookApp                             0x000056d6 -[CoursesViewController tableView:didSelectRowAtIndexPath:] + 374
    11  UIKit                               0x00135b68 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
    12  UIKit                               0x0012bb05 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 219
    13  Foundation                          0x0084579e __NSFireDelayedPerform + 441
    14  CoreFoundation                      0x010248c3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
    15  CoreFoundation                      0x01025e74 __CFRunLoopDoTimer + 1220
    16  CoreFoundation                      0x00f822c9 __CFRunLoopRun + 1817
    17  CoreFoundation                      0x00f81840 CFRunLoopRunSpecific + 208
    18  CoreFoundation                      0x00f81761 CFRunLoopRunInMode + 97
    19  GraphicsServices                    0x012d81c4 GSEventRunModal + 217
    20  GraphicsServices                    0x012d8289 GSEventRun + 115
    21  UIKit                               0x000ccc93 UIApplicationMain + 1160
    22  BookApp                             0x00001ff9 main + 121
    23  BookApp                             0x00001f75 start + 53
)
terminate called after throwing an instance of 'NSException'

从堆栈跟踪中,有趣的部分是:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIDeviceWhiteColor _id]: unrecognized selector sent to instance 0x4d2e2a0'

5 BookApp 0x000079e8-[课程类别视图控制器视图Will出现:]+184

其对应于:

- (void)viewWillAppear:(BOOL)animated {
    //... 
    NSString *sqlQuery =
   [NSString stringWithFormat:
      @"SELECT co.name, co.id, o.location FROM course as co JOIN categories as ca JOIN occasions as o WHERE co.catID = ca.id AND co.catID = %i AND o.courseID = co.id",
      self.selectedCategory._id]; // << The culprit
    //... 

之所以会出现这种情况,是因为self.selectedCategory._id试图向self.selectedCategory发送_id消息,但失败了,self.selectedCategory不是好的类型。

这怎么可能呢

既然我想你肯定self.selectedCategory是预期的类型。。。

仅仅因为self.selectedCategory已经发布,并且它的地址已经被另一个变量重用。。。另一种类型的UIColor实例。。。可能是其他任何东西。

结论

仔细检查self.selectedCategory属性的retain/release:)

旁注

+1用于FMDB建议。。。必须!

您的代码正在泄漏内存。在将临时数组分配给self.courses后,您不会发布。此外,在将课程对象添加到临时数组后,您也不会发布课程对象。对于SQLite操作,我建议您使用FMDB。将SQL查询放在每个视图控制器中以从数据库中获取数据将非常容易管理。同样,遵循这种模式是不好的做法。将FMDB用于所有sqlite目的。为所有sqlite通信创建一个单独的类。

最新更新