非常感谢@Hot Licks的帮助,他指出我的sqlite3代码有什么问题。我修改了代码,sqlite3增加的实时字节消失了。
对于其他新的ios开发人员也可能会面临这个问题,我将原始问题留在后面。
我的新问题是:在乐器的每一代之间仍然存在一些增加的实时字节,但似乎所有对象都是由ios SDK的代码构成的,而不是我的代码。 那么我应该单独增加,不需要担心吗?
1)我在Xcode 5中为ipad创建了一个主细节应用程序;
2)使主控器嵌入Tab键控制器,并添加一个新选项卡,因此主控制器是一个带有2个选项卡的标签栏控制器。所有这些都是在故事板中完成的。
3)删除详细控制器中的默认标签。在详细视图中添加tableview,textview和3个按钮。在tableview中添加原型单元格。所有这些都是在故事板中完成的。
4)将tableview,textview作为outletViewController.h中的插座连接。
@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)修改详细视图控制器中的代码,请在后半部分查看“详细控制器代码的相关片段”
它有问题吗?
非常感谢帮助!!!
较旧的部分:
当我调试我的应用程序时,在模拟器中,内存(实时字节)不断增加,但仪器中没有泄漏。
我的问题是:
我的应用程序是一个主要细节的应用程序,使用ARC,SDK是iOS 7,使用Xcode 5编写代码。
这个应用程序在做什么: 在左主导航中,有许多项目,在右侧详细视图中有一个表格。当用户单击某个项目时,详细信息视图中表格的内容将会更改。
问题是每当我点击主导航中的一个项目时,内存将增加约150K~300K。
代码:
主控制器代码的相关片段:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
LHBPoetry *poetry = poetryArray[indexPath.row];
self.detailViewController.poetryId = poetry.poetryId;
}
详细控制器代码的相关片段:
@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 - >分配。 然后我这样做:
打开一代,I got this。
我比较了所有代,我发现每次单击主导航中的项目时对象都会增加。
它指向sqlite3的代码:
以下是代码片段:
-(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;
}
dataFilePath
中的LHBConstant
方法是:
+(NSString *)dataFilePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
documentDirectory = [documentDirectory stringByAppendingString: @"/p140107"];
return documentDirectory;
}
我还在仪器中使用“memory-> leak”模板,没有泄漏。
有人可以帮帮我吗? 非常感谢!
答案 0 :(得分:1)
return poetry;
- 我不相信这样返回会导致@finally
子句执行。当然sqlite3_finalize(statement);
语句不会被执行。
答案 1 :(得分:0)
到目前为止我已经意识到,如果在视图控制器上有一个私有实例变量并且你弹出它,视图控制器就不会被释放。换句话说,一旦拥有私有实例变量,就不会调用视图控制器的dealloc
方法。例如,你有一个UIView * _v和NSTimer * _t作为私有实例变量,如下所示:
@implementation MyViewController{
UIView *_v;
NSTimer *_t;
}
我正在做的是在视图层次结构中弹出视图控制器之前使它们为零。我认为ARC仍然能够在需要内存后的某个时候解除分配MyViewController。
答案 2 :(得分:0)
你有一些难以回答的问题。
由于一些爱好者的帮助,我将我的问题缩小到从sqlite3获取数据的代码。这些代码有什么问题?
对于Sqlite和调试版本:
NDEBUG
未定义DEBUG
SQLITE_DEBUG
预处理器SQLITE_MEMDEBUG
预处理器否则,SQLite会自动进入“发布”模式(来自sqlite3.c
,第14816行):
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
此外,来自sqlite3.c
,第7780行:
/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
** SQLITE_WIN32_MALLOC // Use Win32 native heap API
** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
** SQLITE_MEMDEBUG // Debugging version of system malloc()
**
** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
** assert() macro is enabled, each call into the Win32 native heap subsystem
** will cause HeapValidate to be called. If heap validation should fail, an
** assertion will be triggered.
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
如果需要,您还可以使用SQLITE_CONFIG_MALLOC
到sqlite3_config
来使用Xcode的内存管理器。看看sqlite3_mem_methods
。它可能有助于跟踪。
另外,请确保从SQLite中调用错误消息字符串sqlite3_free
。
最后,您可以查询SQlite的内存统计信息(来自sqlite3.c
,第1550行):
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** <dd> ^This option takes single argument of type int, interpreted as a
** boolean, which enables or disables the collection of memory allocation
** statistics. ^(When memory allocation statistics are disabled, the
** following SQLite interfaces become non-operational:
** <ul>
** <li> [sqlite3_memory_used()]
** <li> [sqlite3_memory_highwater()]
** <li> [sqlite3_soft_heap_limit64()]
** <li> [sqlite3_status()]
** </ul>)^
** ^Memory allocation statistics are enabled by default unless SQLite is
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
** allocation statistics are disabled by default.
** </dd>