在我的应用程序中,我有一个表视图和一个详细视图。表视图是从数据库查询填充的。我在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'
答案 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
建议......必须!