iOS应用程序,无泄漏,但活动字节增加
多亏@Hot Licks的帮助,他指出了我的sqlite3代码的错误。我修改了代码,增加sqlite3的活动字节消失了 对于其他新的ios开发人员可能也会面临这个问题,我将原始问题留在后面的部分 我的新问题是:在仪器的每一代之间仍然有一些增加的活动字节,但似乎所有的对象都是由ios SDK的代码组成的,而不是我的代码。 那么,我是否应该不去管它,不必担心它 @Hot Clicks说我操作UI的方式可能有问题,所以我详细描述了它: 1) 我在Xcode 5中为ipad创建了一个主细节应用程序 2) 使主控形状嵌入到选项卡栏控制器中,并添加一个新选项卡,这样主控形状就是一个带有两个选项卡的选项卡栏控制器。所有这些都是在故事板中完成的 3) 删除详图控制器中的默认标签。在详细视图中添加一个tableview、一个textview和3个按钮。在tableview中添加原型单元。所有这些都是在故事板中完成的 4) 连接tableview和textview作为detailViewController.h中的出口iOS应用程序,无泄漏,但活动字节增加,ios,objective-c,sqlite,memory-leaks,Ios,Objective C,Sqlite,Memory Leaks,多亏@Hot Licks的帮助,他指出了我的sqlite3代码的错误。我修改了代码,增加sqlite3的活动字节消失了 对于其他新的ios开发人员可能也会面临这个问题,我将原始问题留在后面的部分 我的新问题是:在仪器的每一代之间仍然有一些增加的活动字节,但似乎所有的对象都是由ios SDK的代码组成的,而不是我的代码。 那么,我是否应该不去管它,不必担心它 @Hot Clicks说我操作UI的方式可能有问题,所以我详细描述了它: 1) 我在Xcode 5中为ipad创建了一个主细节应用程序 2
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) IBOutlet UITextView *explanationText;
5) 修改主控制器中的函数:“tableview:DidSelectRowatineXpath”:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
LHBPoetry *poetry = [_searchResults objectAtIndex:indexPath.row];
self.detailViewController.poetryId = poetry.poetryId;
}
6) 修改详细视图控制器中的代码,请在后一部分“详细视图控制器代码的相关片段”中进行检查
有什么问题吗
非常感谢你的帮助
旧的部分:
当我在模拟器中调试我的应用程序时,内存(活动字节)不断增加,但仪器中没有泄漏
我的问题是:
-(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
详图控制器代码的相关片段:
-(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
我读了一本书
在Xcode中,我使用Product->Profile打开仪器,然后选择Memory->Allocations。
然后我会这样做:
-(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;
}
我还在仪器中使用“内存->泄漏”模板,没有泄漏
有人能帮我吗?
非常感谢 到目前为止,我已经意识到,如果视图控制器上有一个私有实例变量,并且您将其弹出,则视图控制器不会被解除分配。换句话说,一旦有了私有实例变量,视图控制器的
dealloc
方法就不会被调用。例如,您有一个UIView*\u v和一个NSTimer*\u t作为私有实例变量,如下所示:
@implementation MyViewController{
UIView *_v;
NSTimer *_t;
}
我要做的是在从视图层次结构弹出视图控制器之前将它们设为零。我认为ARC在需要内存后仍然能够释放MyViewController 你有些问题很难回答 由于一些热心者的帮助,我把问题缩小到了从sqlite3获取数据的代码上。这些代码有什么问题 对于Sqlite和调试版本:
NDEBUG
DEBUG
SQLITE\u调试预处理器
SQLITE\u MEMDEBUG
预处理器sqlite3.c
,第14816行):
另外,从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\u CONFIG\u MALLOC
到sqlite3\u CONFIG
来使用Xcode的内存管理器。看看sqlite3\u mem\u方法
。它可能有助于跟踪。
另外,请确保您正在对来自SQLite的错误消息字符串调用sqlite3\u free
最后,您可以查询SQlite的内存统计信息(从sqlite3.c
,第1550行):
**[[SQLITE\u CONFIG\u MEMSTATUS]]SQLITE\u CONFIG\u MEMSTATUS
**^此选项接受int类型的单个参数,解释为
**布尔值,用于启用或禁用内存分配集合
**统计数字^(禁用内存分配统计信息时
**以下SQLite接口变得不可操作:
**
**- [sqlite3\u内存使用()
**
- [sqlite3\u memory\u highwater()]
**
- [sqlite3\u soft\u heap\u limit64()]
**
- [sqlite3_status()]
**
)^
**^除非启用SQLite,否则默认情况下将启用内存分配统计信息
**编译时[SQLITE\u DEFAULT\u MEMSTATUS]=0,在这种情况下为内存
**默认情况下禁用分配统计信息。
**
返回诗歌
--我不相信这样返回会导致执行@finally
子句。当然还有sqlite3_finalize(语句)代码>语句执行