【问题标题】:Memory management with GCD, NSMutableArray and UITableView [closed]使用 GCD、NSMutableArray 和 UITableView 进行内存管理 [关闭]
【发布时间】:2013-05-06 22:56:49
【问题描述】:

我现在被这个错误“EXC_BAD_ACCESS”困扰了好几个小时,我似乎找不到问题所在。希望你们中的一些人会找到它。

我正在下载一个包含 json-data 的文件,将其保存为 NSMutableArray 中的自定义 NSObject,然后将其呈现在 UITableView 中。当我要在 UITableView 中呈现它时,我遇到了问题。

ViewController.h

@property (nonatomic, retain) NSMutableArray *menuItems;

ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    menuItems = [[NSMutableArray alloc] init];
}

- (void)viewDidAppear:(BOOL)animated
{
    [self downloadMenu];

}

-(void)downloadMenu
{
    dispatch_queue_t fetchfromServerQueue = dispatch_queue_create("fetchfromServer", NULL);

    [self createProgressionAlertWithMessage:@"Fetching menu"];

    dispatch_async(fetchfromServerQueue, ^{

        NSURL *menuURL = [NSURL URLWithString:@"anURL"];

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:menuURL];

        NSError *error = nil;
        NSURLResponse *response;
        NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

        responseArray = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];

        menuItems = [[NSMutableArray alloc] initWithCapacity:[responseArray count]];

        for (int i = 0; i<[responseArray count]; i++) {
            NSDictionary *menuObject = [responseArray objectAtIndex:i];

            NSString *x = [NSString stringWithFormat:@"%@", [menuObject objectForKey:@"x"]];
            NSString *y = [NSString stringWithFormat:@"%@", [menuObject objectForKey:@"y"]];
            NSString *z = [NSString stringWithFormat:@"%@", [menuObject objectForKey:@"z"]];

            MenuItem *menuItem = [[MenuItem alloc] initWithX:x andY:y andZ:z];

            [menuItems addObject:menuItem];

            [menuItem release];
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [progressAlert dismissWithClickedButtonIndex:0 animated:YES];
            [menuTable reloadData];
        });
    });
    dispatch_release(fetchfromServerQueue);
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [menuItems count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    MenuItem *menuItem = (MenuItem *)[menuItems objectAtIndex:indexPath.row];

    cell.textLabel.text = [NSString stringWithFormat:@"%@", [menuItem x]];

    return cell;
}

在 "cell.textLabel.text = [NSString stringWithFormat:@"%@", [menuItem x]];"我得到“EXC_BAD_ACCESS (code=1,address=0xXXXXXXXX)”。

我不使用 ARC,并且在不久的将来无法通过此项目转换为它。由于我缺乏内存管理知识,这使它成为一个问题。

知道哪里出了问题吗?

谢谢!

#### #### #### #### #### #### #### #### ####

这就是 MenuItem 的样子:

#import <Foundation/Foundation.h>

@interface MenuItem : NSObject
{
    NSString *x;
    NSString *y;
    NSString *z;
}

-(id)initWithX:(NSString *)x_ andY:(NSString *)y_ andZ:(NSString *)z_;
-(NSString *)x;
-(NSString *)y;
-(NSString *)z;

@property(retain, nonatomic) NSString *x;
@property(retain, nonatomic) NSString *y;
@property(retain, nonatomic) NSString *z;

@end

#import "MenuItem.h"

@implementation MenuItem

@synthesize x;
@synthesize y;
@synthesize z;

-(id)initWithX:(NSString *)x_ andY:(NSString *)y_ andZ:(NSString *)z_
{
    self = [super init];
    if(self)
    {
        x = x_;
        y = y_;
        z = z_;
    }

    return self;
}

-(void)dealloc
{
    [x release];
    [y release];
    [z release];
    [super dealloc];
}

-(NSString *)x
{
return x;
}

-(NSString *)y
{
    return y;
}

-(NSString *)z
{
    return z;
}

@end

【问题讨论】:

    标签: objective-c ios5 memory-management ios6 exc-bad-access


    【解决方案1】:

    我没有看到任何明显的东西,也许menuItem 中的某些东西导致了这个问题? [menuItem x] 是做什么的?

    一般来说,使用僵尸工具运行应用程序:cmd-i,然后选择 Zombies。这将为您提供抛出 EXC_BAD_ACCESS 的对象的分配/释放跟踪。

    祝你好运。

    【讨论】:

    • 我的疯狂猜测:您的第一段是正确的,但第二段有点偏离。我打赌x 是什么,它不是一个对象。
    • 我添加了 MenuItem 的代码。 x 是 NSString。你觉得这门课有什么问题吗?
    • 今天晚些时候我会试试僵尸。
    • @TimBjärengren:嗯,我错了,亚当是对的。您没有保留或复制 init 方法中的字符串。 Zombies 仪器确实应该抓住这一点。
    • 谢谢你们,你们太棒了!
    【解决方案2】:

    这有点奇怪:

    -(void)downloadMenu
    {
        dispatch_queue_t fetchfromServerQueue = dispatch_queue_create("fetchfromServer", NULL);
        dispatch_async(fetchfromServerQueue, ^{
            ...
        });
        dispatch_release(fetchfromServerQueue);
    }
    

    您创建一个队列并为其分配一个异步任务。当该任务开始做一些工作时,您会立即释放队列。如果异步任务在您释放之前未完成,这可能会导致一些问题。

    您可能希望在异步调用中的工作完成之前推迟发布。

    【讨论】:

    • 这不是问题; Block 保留队列,直到它完成运行。见docs for dispatch_queue_create()中的“讨论”
    • 很公平。我正在查看示例oq,他们将发布放在回调中。
    猜你喜欢
    • 2011-07-01
    • 2011-09-06
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    相关资源
    最近更新 更多