objective-c - 分配内存

标签 objective-c ios memory-management

我的应用程序存在内存分配问题。这导致我的程序卡住并最终结束。查看我的代码,我意识到大部分内存分配都在 CFString 中。下面是导致此问题的类。

#import "iMAPProdutosPesquisar.h"
#import "iMAPArrayProdutos.h"
#import "iMAPTabela.h"
#import "iMAPProdutosFiltro.h"
#import "iMAPArrayAbreviatura.h"

static NSString *dadosProdutos = nil;

@implementation iMAPProdutosPesquisar

@synthesize pop;
@synthesize tv;
@synthesize sb;
@synthesize datBaseName;
@synthesize datBasePath;
@synthesize iMAP;
@synthesize abrev;
@synthesize opcFil;
@synthesize cab;
@synthesize cons;

#define TAG_1 1 
#define TAG_2 2
#define TAG_3 3

#define FIRST_CELL_IDENTIFIER @"TrailItemCell" 
#define SECOND_CELL_IDENTIFIER @"RegularCell"

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        // Custom initialization
    }

    return self;
}

- (void)dealloc {

    [pop release];
    [tv release];
    [sb release];
    [datBaseName release];
    [datBasePath release];
    [iMAP release];
    [abrev release];
    [opcFil release];
    [cab release];
    [cons release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning {

    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view from its nib.
    [self initDatBase];

    [cab setImage:[UIImage imageNamed:@"cabecalho-produtos.png"]];
    cab.opaque = YES;
}

- (void)viewDidUnload {

    [self setPop:nil];
    [self setTv:nil];
    [self setSb:nil];
    [self setDatBaseName:nil];
    [self setDatBasePath:nil];
    [self setIMAP:nil];
    [self setAbrev:nil];
    [self setOpcFil:nil];
    [self setCab:nil];
    [self setCons:nil];
    [super viewDidUnload];

    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark UISearchBarDelegate

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {

    [self initDatBase];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {

    [searchBar resignFirstResponder];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {

    [searchBar resignFirstResponder];
}

#pragma mark tableView delegates

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  {

    tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;

    return [iMAP count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  {

    iMAPArrayProdutos *arrayProd = (iMAPArrayProdutos *)[iMAP objectAtIndex:indexPath.row];

    NSString *myIdent = @"myIdent";

    iMAPTabela *tab = (iMAPTabela *)[tableView dequeueReusableCellWithIdentifier:myIdent];

    tv.autoresizesSubviews = YES;

    if (tab == nil) {

        tab = [[[iMAPTabela alloc] initWithFrame:CGRectZero reuseIdentifier:myIdent] autorelease];

        UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(10.0, 0, 150.0, tableView.rowHeight)] autorelease];

        [tab addColumn:170];

        label.tag = TAG_1; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = arrayProd.cod;
        label.textAlignment = UITextAlignmentLeft; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [tab.contentView addSubview:label]; 

        label =  [[[UILabel alloc] initWithFrame:CGRectMake(180.0, 0, 150.0, tableView.rowHeight)] autorelease]; 

        [tab addColumn:340];

        label.tag = TAG_2; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = arrayProd.artrf2;
        label.textAlignment = UITextAlignmentLeft; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [tab.contentView addSubview:label];

        label =  [[[UILabel alloc] initWithFrame:CGRectMake(350.0, 0, 418.0, tableView.rowHeight)] autorelease]; 

        [tab addColumn:768];

        label.tag = TAG_3; 
        label.font = [UIFont systemFontOfSize:14.0]; 
        label.text = arrayProd.descri;    
        label.textAlignment = UITextAlignmentLeft; 
        label.textColor = [UIColor blackColor]; 
        label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight; 

        [tab.contentView addSubview:label];
    }

    UILabel *label_1 = (UILabel *)[tab.contentView viewWithTag:TAG_1];
    label_1.text = arrayProd.cod;

    UILabel *label_2 = (UILabel *)[tab.contentView viewWithTag:TAG_2];
    label_2.text = arrayProd.artrf2;

    UILabel *label_3 = (UILabel *)[tab.contentView viewWithTag:TAG_3];
    label_3.text = arrayProd.descri;

    return tab;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    iMAPArrayProdutos *arrayProd = (iMAPArrayProdutos *)[iMAP objectAtIndex:indexPath.row];

    [iMAPProdutosPesquisar setDefaultValue:[NSString stringWithFormat:@"%@", arrayProd.cod]];
}

- (IBAction)fil:(id)sender {

    iMAPProdutosFiltro *prodFil = [[iMAPProdutosFiltro alloc] init];
    pop = [[UIPopoverController alloc] initWithContentViewController:prodFil];

    prodFil.pop = pop;

    [prodFil release];

    [pop setPopoverContentSize:CGSizeMake(170, 220)];
    [pop presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

- (void)initDatBase {

    datBaseName = @"iMAP.sqlite";

    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [documentPaths objectAtIndex:0];

    datBasePath = [documentsDir stringByAppendingPathComponent:datBaseName];

    [self checkAndCreateDatBase];
    [self readFilFromDatBase];

    if ([sb.text length] > 0) {

        [self readAvancFromDatBase];
    }

    [self readProdFromDatBase];
}

- (void)checkAndCreateDatBase {

    BOOL success;

    NSFileManager *fileManager = [NSFileManager defaultManager];

    success = [fileManager fileExistsAtPath:datBasePath];

    if(success) {

        return;
    }

    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:datBaseName];

    [fileManager copyItemAtPath:databasePathFromApp toPath:datBasePath error:nil];

    [fileManager release];
}

- (void)readFilFromDatBase {

    sqlite3 *datBase;

    if(sqlite3_open([datBasePath UTF8String], &datBase) == SQLITE_OK) {

        const char *sqlStat = "SELECT OPCAO FROM FILTRO WHERE R_E_C_N_O_ = 2";
        sqlite3_stmt *compiledStat;

        if(sqlite3_prepare_v2(datBase, sqlStat, -1, &compiledStat, NULL) == SQLITE_OK) {

            while(sqlite3_step(compiledStat) == SQLITE_ROW) {

                opcFil = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStat, 0)];
            }
        }

        sqlite3_finalize(compiledStat);
    }

    sqlite3_close(datBase);
}

- (void)readAvancFromDatBase {

    sqlite3 *datBase;

    abrev = [[NSMutableArray alloc] init];

    if(sqlite3_open([datBasePath UTF8String], &datBase) == SQLITE_OK) {

        const char *sqlStat;
        sqlite3_stmt *compiledStat;

        NSString *string1;
        NSString *string2;

        string1 = @"SELECT ABV_COMPLETA FROM ABREV WHERE ABV_REDUZ LIKE '%";
        string2 = @"%'";

        NSString *result =  [NSString stringWithFormat:@"%@%@%@", string1, sb.text, string2]; 

        sqlStat = [result UTF8String];

        if(sqlite3_prepare_v2(datBase, sqlStat, -1, &compiledStat, NULL) == SQLITE_OK) {

            while(sqlite3_step(compiledStat) == SQLITE_ROW) {

                NSString *abvCompl = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStat, 0)];

                iMAPArrayAbreviatura *arrayAbrev = [[iMAPArrayAbreviatura alloc] reduz:nil completa:abvCompl observacao:nil abrUnq:nil recno:nil];

                [abrev addObject:arrayAbrev];

                [arrayAbrev release];
            }
        }

        sqlite3_finalize(compiledStat);
    }

    sqlite3_close(datBase);
}

- (void)readProdFromDatBase {

    sqlite3 *datBase;

    iMAP = [[NSMutableArray alloc] init];

    if(sqlite3_open([datBasePath UTF8String], &datBase) == SQLITE_OK) {

        sqlite3_stmt *compiledStat;
        const char *sqlStat;

        if ([sb.text length] == 0) {

            sqlStat = "SELECT COD, ARTRF2, DESCRI FROM APSB1010";
        }
        else {

            NSString *string1;
            NSString *string2 = @"%'";
            NSString *result;

            if ([opcFil isEqualToString:@"1"]) {

                string1 = @"SELECT COD, ARTRF2, DESCRI FROM APSB1010 WHERE TRIM(COD) LIKE '%";

                result = [NSString stringWithFormat:@"%@%@%@", string1, sb.text, string2]; 
            }
            else if ([opcFil isEqualToString:@"2"]) {

                string1 = @"SELECT COD, ARTRF2, DESCRI FROM APSB1010 WHERE TRIM(ARTRF2) LIKE '%";

                result = [NSString stringWithFormat:@"%@%@%@", string1, sb.text, string2];
            }
            else if ([opcFil isEqualToString:@"3"]) {

                string1 = @"SELECT COD, ARTRF2, DESCRI FROM APSB1010 WHERE TRIM(DESCRI) LIKE '%";

                result = [NSString stringWithFormat:@"%@%@%@", string1, sb.text, string2];
            }
            else if ([opcFil isEqualToString:@"4"]) {

                string1 = @"SELECT COD, ARTRF2, DESCRI FROM APSB1010 WHERE TRIM(APLICA) LIKE '%";

                result = [NSString stringWithFormat:@"%@%@%@", string1, sb.text, string2];
            }
            else {

                string1 = @"SELECT COD, ARTRF2, DESCRI FROM APSB1010 WHERE (";
                NSString *string1 = @"SELECT * FROM APSB1010 WHERE (";
                NSString *string3 = @"TRIM(DESCRI) LIKE '%";
                NSString *string4 = @" OR ";
                NSString *string5 = @")";
                cons = [[NSString alloc] init];

                for (int i = 0; i < [abrev count]; i++) {

                    iMAPArrayAbreviatura *arrayAbrev = (iMAPArrayAbreviatura *)[abrev objectAtIndex:i];

                    if (i > 0) {

                        cons = [cons stringByAppendingString:string4];
                    }

                    cons = [cons stringByAppendingString:string3];
                    cons = [cons stringByAppendingString:arrayAbrev.completa];
                    cons = [cons stringByAppendingString:string2];
                }

                result = [NSString stringWithFormat:@"%@%@%@", string1, cons, string5];
            }

            sqlStat = [result UTF8String];
        }

        if(sqlite3_prepare_v2(datBase, sqlStat, -1, &compiledStat, NULL) == SQLITE_OK) {

            while(sqlite3_step(compiledStat) == SQLITE_ROW) {

                NSString *prodCod = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStat, 0)];
                NSString *prodDescri = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStat, 2)];
                NSString *prodArtrf2 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStat, 1)];

                iMAPArrayProdutos *arrayProd = [[iMAPArrayProdutos alloc] cod:prodCod prv1:nil grupo:nil picment:nil descri:prodDescri artrf2:prodArtrf2 um:nil embAp:nil desMax:nil imgAp:nil aplica:nil qAtu_01:nil qAtu_11:nil qAtu_12:nil qAtu_13:nil qAtu_14:nil prProm:nil recno:nil];

                [iMAP addObject: arrayProd];

                [arrayProd release];
            }
        }

        sqlite3_finalize(compiledStat);
    }

    sqlite3_close(datBase);

    [tv reloadData];
}

+ (NSString*)defaultValue {

    return dadosProdutos;
}

+ (void)setDefaultValue:(NSString*)newDefaultValue {

    if(dadosProdutos != newDefaultValue) {

        [dadosProdutos release];

        dadosProdutos = [newDefaultValue retain];
    }
}

@end

有人告诉我我做错了什么,我被这个问题弄疯了。

最佳答案

你有很多地方可以做类似的事情

datBaseName = @"iMAP.sqlite";

我假设 datBaseName 被定义为一个保留的属性,但是这里只是设置实例变量而不调用访问器,所以当你调用

[datBaseName release]

你正试图释放一个常量字符串——不好的事情会发生。相反,你应该这样做

self.datBaseName = @"iMAP.sqlite";

你也在做这样的事情

datBasePath = [documentsDir stringByAppendingPathComponent:datBaseName];

同样,这并没有调用访问器,因此 datBasePath 没有被保留,并且可能在您尝试使用它时已经被释放。

很可能还有其他问题 - 尝试将问题简化为更简单的示例,这样问题更容易被发现。另请查看 ARC这消除了内存管理中的一些苦差事。 Xcode 也有一堆工具,例如 NSZombies 用于跟踪此类问题。

关于objective-c - 分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8635329/

相关文章:

c# - 内存管理——C# VS Objective C?

objective-c - 在 Objective-C 中声明静态变量的正确方法是什么?

php - 在 iOS 中进行 JSON 序列化时失败,但通过浏览器访问时 API 正常

c++ - 是否可以从现有基类动态分配派生类所需的额外内存?

ios - 如何更新在 UITableViewCell 中添加的 View ?

ios - 抑制链接器警告 : "Meta method X in category from Y overrides method from class in Z"

iOS 代码签名 FaSTLane 匹配错误

objective-c - 如何使用AFNetwork下载多个文件

python - 在 Python 中重用名称以节省内存

perl - 我应该使用哪个工具来找出 Perl 中的内存分配?