Thanks a lot to @Hot Licks's help, He points out what's wrong with my sqlite3's codes. I modify the codes and the live bytes increasing by sqlite3 are gone.
For other new ios developers may also face this problem, I leave the original questions in the latter part.
My new question is: there still are some increasing live bytes between every generation in instruments, but it seems that all the objects are made of ios SDK's codes, not my codes. So should I leave the increasing alone, and don't need to worry about it?
@Hot Licks says there may be a problem in my way to manipulate the UI, so I describe it in detail:
1) I create a master detail app for ipad in Xcode 5;
2) Make the master embed in Tab bar controller, and add one new tab, so the master is a tab bar controller with 2 tabs. All these things are done in storyboard.
3) Delete the default label in the detail controller. Add a tableview, a textview and 3 buttons in the detail view. Add a prototype cell in the tableview. All these things are done in storyboard.
4) Connect the tableview, the textview as an outlet in detailViewController.h.
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) IBOutlet UITextView *explanationText;
5) modify the function: "tableview: didSelectRowAtIndexPath" in the master controller:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
LHBPoetry *poetry = [_searchResults objectAtIndex:indexPath.row];
self.detailViewController.poetryId = poetry.poetryId;
}
6) modify the codes in detail view controller, please check it in the latter part, "a related snippet of the detail controller's code"
Is there a problem in it?
Thanks a lot for helping!!!
The older part :
When I debug my app, in simulator, the memory (live bytes) is continuously increasing, but there is no leaking in Instruments.
My questions are:
My app is a master-detail app, using ARC, SDK is iOS 7, using Xcode 5 to write code.
What is this app doing: In the left master navigation, there are many items, and in the right detail view there is a table. When users click on an item, the contents of the table in the detail view will change.
The problem is every time I click on an item in the master navigation, the memory will increase for about 150K~300K.
Code:
a related snippet of the master controller's code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
LHBPoetry *poetry = poetryArray[indexPath.row];
self.detailViewController.poetryId = poetry.poetryId;
}
a related snippet of the detail controller's code:
@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
I read an this article about using Heapshot Analysis to find a leak.
In Xcode, I use Product->Profile, to open instruments, then select Memory -> Allocations. Then I do this:
I got results from instruments.
open an generation, I got this.
I compare all the generations, and I find that an object increases every time I click an item in master navigation.
It points to codes of sqlite3:
Here is the snippet of code:
-(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;
}
and the method dataFilePath
in LHBConstant
is:
+(NSString *)dataFilePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
documentDirectory = [documentDirectory stringByAppendingString: @"/p140107"];
return documentDirectory;
}
I also use "memory->leak" template in instruments, there's no leak.
Anyone could help me out? Thanks a lot!
return poetry;
-- I'm not convinced that returning like that will cause the @finally
clause to execute. And certainly the sqlite3_finalize(statement);
statement does not get executed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With