【发布时间】:2014-01-23 22:15:44
【问题描述】:
非常感谢@Hot Licks 的帮助,他指出了我的 sqlite3 代码有什么问题。我修改了代码,通过 sqlite3 增加的活动字节消失了。
对于其他新的ios开发者也可能面临这个问题,我把原来的问题留在了后面。
我的新问题是:仪器的每一代之间仍有一些增加的活动字节,但似乎所有对象都是由 ios SDK 的代码组成的,而不是我的代码。 那我应该不理会增加的事情,不用担心吗?
@Hot Licks 说我操作 UI 的方式可能有问题,所以我详细描述一下:
1) 我在 Xcode 5 中为 ipad 创建了一个主从应用程序;
2) 将master嵌入到Tab bar控制器中,并添加一个新的tab,所以master是一个有2个tab的tab bar控制器。所有这些事情都在故事板中完成。
3) 删除细节控制器中的默认标签。在详细视图中添加一个表格视图、一个文本视图和 3 个按钮。在 tableview 中添加一个原型单元格。所有这些事情都在故事板中完成。
4)在detailViewController.h中连接tableview,textview作为outlet。
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) IBOutlet UITextView *explanationText;
5)修改主控制器中的函数:“tableview:didSelectRowAtIndexPath”:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
LHBPoetry *poetry = [_searchResults objectAtIndex:indexPath.row];
self.detailViewController.poetryId = poetry.poetryId;
}
6) 修改detail view controller的代码,请看后面的“detail controller's code的相关sn-p”
这里面有问题吗?
非常感谢您的帮助!!!
旧部分:
当我在模拟器中调试我的应用程序时,内存(实时字节)不断增加,但 Instruments 中没有泄漏。
我的问题是:
- 我的代码有什么问题?我想也许每次我点击一个项目时,都会重新创建详细信息的界面?
- 如何找到泄露的代码?
- 由于一些爱好者的帮助,我将我的问题缩小到关于从 sqlite3 获取数据的代码。这些代码有什么问题?
- 我创建了一个默认的主从应用程序,我多次单击master中的项目,它的活字节也增加了。那么这是否意味着我不需要担心这个问题?
我的app是master-detail app,使用ARC,SDK是iOS 7,使用Xcode 5写代码。
这个应用程序在做什么: 在左侧的主导航中,有很多项,在右侧的详细视图中有一个表格。当用户点击某个项目时,详细视图中的表格内容会发生变化。
问题是每次在主导航中点击一个item,内存会增加150K~300K左右。
代码:
主控制器代码的相关sn-p:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
LHBPoetry *poetry = poetryArray[indexPath.row];
self.detailViewController.poetryId = poetry.poetryId;
}
详细控制器代码的相关sn-p:
@interface LHBDetailViewController (){
LHBPoetry *poetry;
NSArray *sentenceArray;
PoetryDao *poetryDao;
PoetryService *poetryService;
}
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
- (void)configureView;
@end
@implementation LHBDetailViewController
#pragma mark - Managing the detail item
- (void)setPoetryId:(int)poetryId
{
if (_poetryId != poetryId) {
_poetryId = poetryId;
// Update the view.
[self configureView];
}
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.poetryId > 0) {
poetry = [poetryDao getPoetryById:self.poetryId];
}else{
poetry = [poetryDao getPoetryById:1];
}
if(poetry != nil){
//custom title
if(poetry.dynasty != nil){
self.title = [NSString stringWithFormat:@"%@ [%@]%@", poetry.name, poetry.dynasty, poetry.author];
}else{
self.title = [NSString stringWithFormat:@"%@ %@", poetry.name, poetry.author];
}
//refresh sentenceArray
sentenceArray = [poetryService changeStringToArray:poetry.content withSplitter:[LHBConstant getPoetrySplitter]];
}else{
//custom title
self.title = @"";
}
[_tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
poetryDao = [[PoetryDao alloc] init];
poetryService = [[PoetryService alloc] init];
[self configureView];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"detailCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSString *sentence = sentenceArray[indexPath.row];
cell.textLabel.text = sentence;
return cell;
}
@end
我读到了this article about using Heapshot Analysis to find a leak。
在 Xcode 中,我使用 Product->Profile 打开仪器,然后选择 Memory -> Allocations。 然后我这样做:
- 在仪器中,点击“标记生成”;
- 在我的应用程序中,单击主视图中的一个项目。 重复这 2 个步骤几次。
开启一代,I got this。
我比较了所有的世代,我发现每次单击主导航中的一个项目时,一个对象都会增加。
它指向sqlite3的代码:
这里是sn-p的代码:
-(LHBPoetry *) getPoetryById:(int) poetryId{
sqlite3 *database;
@try{
//open database
if(sqlite3_open([[LHBConstant dataFilePath] UTF8String], &database)!=SQLITE_OK){
sqlite3_close(database);
NSAssert(0, @"Failed to open database.");
}
//find in database
NSString *query = @"SELECT id,name,author,dynasty, content, explanation, has_license, has_mastered FROM poetry where id = ?";
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil)==SQLITE_OK){
//bind parameter
sqlite3_bind_int(statement, 1, poetryId);
while (sqlite3_step(statement)==SQLITE_ROW) {
int primaryId = sqlite3_column_int(statement, 0);
char *name = (char *)sqlite3_column_text(statement, 1);
char *author = (char *)sqlite3_column_text(statement, 2);
char *dynasty = (char *)sqlite3_column_text(statement, 3);
char *content = (char *)sqlite3_column_text(statement, 4);
char *explanation = (char *)sqlite3_column_text(statement, 5);
int hasLicense = sqlite3_column_int(statement, 6);
int hasMastered = sqlite3_column_int(statement, 7);
NSString *nameNS = [NSString stringWithUTF8String:name];
NSString *authorNS = [NSString stringWithUTF8String:author];
NSString *dynastyNS = dynasty == nil ? NULL : [NSString stringWithUTF8String:dynasty];
NSString *contentNS = [NSString stringWithUTF8String:content];
NSString *explanationNS = explanation == nil ? NULL : [NSString stringWithUTF8String:explanation];
LHBPoetry *poetry = [[LHBPoetry alloc] initWithId:primaryId withName:nameNS withAuthor:authorNS withDynasty:dynastyNS withContent:contentNS withExplanation:explanationNS withLicense:hasLicense withMastered:hasMastered];
return poetry;
}
sqlite3_finalize(statement);
}else{
NSLog(@"poetry getPoetryById fail. database is not ready.");
}
}
@catch (NSException *e) {
NSLog(@"%@", e);
}
@finally {
sqlite3_close(database);
}
return nil;
}
而LHBConstant中的方法dataFilePath是:
+(NSString *)dataFilePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
documentDirectory = [documentDirectory stringByAppendingString: @"/p140107"];
return documentDirectory;
}
我也在仪器中使用“memory->leak”模板,没有泄漏。
谁能帮帮我? 非常感谢!
【问题讨论】:
-
请注意
IOS与iOS不同。IOS代表en.wikipedia.org/wiki/Cisco_IOS 而iOS代表en.wikipedia.org/wiki/IOS -
如果您仔细研究仪器结果,您很可能会发现某些特定类别的对象正在积累越来越多的实例。什么样的对象可能会导致您遇到问题。
-
@HotLicks 非常感谢!正如我在这个问题中提到的那样,我试图查看仪器中的结果,我遵循了关于使用仪器查找泄漏的教程。但我是一个新的 ios 开发人员,我对此一无所知......
-
@abentotoro 尝试评论任何复杂的代码并运行您的项目,看看是否仍然遇到同样的问题
-
因为前天我有同样的内存问题,我在编码时犯了一个简单的错误,导致 1gb 活动字节
标签: ios objective-c sqlite memory-leaks