从详细信息视图iphone返回时,tableView崩溃

时间:2011-06-14 10:37:16

标签: iphone cocoa-touch uitableview

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

* 修改 * 以下是数据库中的代码,我使用它来填充表格视图: *

- (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'

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

  

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

  

5 BookApp 0x000079e8 - [CoursesCategoriesViewController viewWillAppear:] + 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尝试向_id发送self.selectedCategory消息而失败,self.selectedCategory不是好的类型。

怎么可能这样呢?

因为我猜你确定self.selectedCategory是期​​望的类型......

只是因为self.selectedCategory已被释放,并且其地址已被重新用于另一种类型的另一种变量......在你的跟踪中一个UIColor实例......可能是其他任何东西。

结论

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

旁注

+1 FMDB建议......必须!