【问题标题】:NSMutableArray EXC_BAD_ACCESS on contained objectsNSMutableArray EXC_BAD_ACCESS 在包含的对象上
【发布时间】:2011-03-20 09:20:24
【问题描述】:

我有一个实现 NSMutableArray 对象的类。现在,当手机进入横向模式时,NSMutableArray 中的所有对象都从视图中删除(但不是从 NSMutableArray 中),然后当手机返回纵向模式时,我将 NSMutableArray 中包含的所有对象放入视图,但是当我尝试访问收到的第一个对象时:EXC_BAD_ACCESS。

这是我的代码:

- (void) setObjects:(BOOL)hidden andWindow:(UIWindow *)win andTxt:(UITextView *)txt andTarget:(id) target {
    //view
    key = [win.subviews objectAtIndex:0];
    key.hidden = hidden;
    buttons = [[NSMutableArray alloc] initWithCapacity:1]; //my array
    txtsms = txt;
        [...]
}

- (void) addButton:(button *)but {
    [key addSubview:[but returnButton]];
    [buttons addObject:but];
    [but release];
}

- (void) hiddenAllKey {
    for (UIView *subview in [key subviews])
        if ((subview.tag <= startSpecialPunctuation+1)&&(subview.tag >= spaceButton+1)) 
            [subview removeFromSuperview];
}

- (void) showAllKey {   
    for(int i = 0; i < [buttons count]; ++i)
             [key addSubview:[[buttons objectAtIndex:i] returnButton]]; //this is the problem :|
}

【问题讨论】:

  • @Joe - 你是对的,没有“可能”。如果您尝试创建或保留按钮,则不应在此处释放它。

标签: iphone objective-c memory-management exc-bad-access


【解决方案1】:

正如 Joe Blow 所说,这是错误的:

- (void) addButton:(button *)but {
    [key addSubview:[but returnButton]];
    [buttons addObject:but];
    [but release];
}

but 不应在该方法中释放。同样,这让我心生恐惧:

- (void) setObjects:(BOOL)hidden andWindow:(UIWindow *)win andTxt:(UITextView *)txt andTarget:(id) target {
    //view
    key = [win.subviews objectAtIndex:0];
    key.hidden = hidden;
    buttons = [[NSMutableArray alloc] initWithCapacity:1]; //my array

你在哪里发布buttons?您的应用是否只调用该方法一次?如果没有,那么您将泄露buttons

在您的代码上尝试build and analyze,修复它发现的任何问题。如果它仍然崩溃,请发布崩溃的回溯

【讨论】:

    【解决方案2】:
    - (void) hiddenAllKey {
        for (UIView *subview in [key subviews])
            if ((subview.tag <= startSpecialPunctuation+1)&&(subview.tag >= spaceButton+1)) 
                [subview removeFromSuperview];
    }
    

    这也是微妙的错误。您正在使用快速枚举从列表中删除元素。它可能(应该)很容易失败。

    以前,我在 UIView 上编写了一个类别来执行全部删除,这可以通过一个简单的 while 循环来实现。现在,您正在尝试做的事情......您可能会执行一个 for 循环,您自己管理迭代索引,即当您不删除时,您递增,否则您保持不变。

    编辑:解决方案建议:

    for (int idx = 0; idx < [[key subviews] count]; )
    {
        UIView *subview = [[key subviews] objectAtIndex: idx];
        if ((subview.tag <= startSpecialPunctuation + 1) && (subview.tag >= spaceButton + 1))
        {
            [subview removeFromSuperview];
        }
        else
        {
            idx++;
        }
    }
    

    【讨论】:

    • 你能把你的解决方案链接给我吗?
    • 我将使用 your 案例的可能解决方案来编辑​​我的答案,这不是我在我的案例中所做的。
    • 好吧,我现在无法测试它,由于 removeFromSuperview 性质,它可能无法工作:(
    • 我确定 while (list != empty) removeView;循环确实有效,所以这应该是可行的。
    • 问题是我有一个 textField,如果我删除它,你的代码(和我的代码)不起作用,如果我隐藏它,你的代码(和我的)工作正常......我不明白为什么:|
    猜你喜欢
    • 1970-01-01
    • 2013-11-08
    • 2015-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多