【问题标题】:Objective-C IOS Xcode: Unable to modify object in NSMutableArrayObjective-C IOS Xcode:无法修改 NSMutableArray 中的对象
【发布时间】:2013-01-16 19:31:17
【问题描述】:

我的问题是我有一个 NSMutableArray 类型的类属性,如我的头文件中所定义,但是当我尝试修改其中一个数组元素(NSDictionary)时,我收到以下运行时错误:

2013-01-16 14:17:20.993 debtaculous[5674:c07] * 终止应用程序到期 未捕获的异常“NSInternalInconsistencyException”,原因: '-[__NSCFArray replaceObjectAtIndex:withObject:]: 变异方法发送 到不可变对象'

标头声明:

//  BudgetViewController.h

#import <UIKit/UIKit.h>

@interface BudgetViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
- (IBAction)afterTaxIncomeEditingDidEnd:(id)sender;
@property (strong, nonatomic) NSMutableArray *budgetArray;
@property (strong, nonatomic) IBOutlet UITextField *afterTaxIncome;
@property (strong, nonatomic) IBOutlet UITableView *budgetTableView;

@end

产生错误的方法:

-(void)applyCCCSWeights
{
    NSMutableDictionary *valueDict;
    NSString *newAmount;

    for (id budgetElement in [self budgetArray]) {
        valueDict = [[NSMutableDictionary alloc] initWithDictionary:budgetElement];
        newAmount = [NSString stringWithFormat:@"%0.2f", [[self afterTaxIncome].text floatValue] * [[budgetElement objectForKey:@"cccs_weight"] floatValue]];
        [valueDict setValue:newAmount forKeyPath:@"amount"];

        [[self budgetArray] replaceObjectAtIndex:0 withObject:valueDict];
        NSLog(@"%0.2f (%0.2f)", [[budgetElement objectForKey:@"amount"] floatValue], [[self afterTaxIncome].text floatValue] * [[budgetElement objectForKey:@"cccs_weight"] floatValue]);
    }

    [self.budgetTableView reloadData];
}

// 注意上面的replaceObjectAtIndex:0 只是一个占位符。这将替换为正确的索引。

【问题讨论】:

  • 你在哪里初始化你的数组?
  • 能否贴出初始化budgetArray的代码
  • 主要部分:[self setUrlData:[NSURLConnection sendSynchronousRequest:request returnedResponse:&response error:&error]]; [self setBudgetArray:[NSJSONSerialization JSONObjectWithData:[self urlData] options:kNilOptions error:&error]];
  • 你去...查看 NSJSONSerialization 中的选项。使用一种创建可变数组和字典的方法。

标签: ios objective-c xcode nsmutablearray


【解决方案1】:

budgetArray 肯定是不可变的,你必须创建它是可变的。

可能你正在做这样的事情:

budgetArray= [NSArray arraWithObjects; obj1, obj2, nil];

并忽略编译器警告。使其可变:

budgetArray= [[NSMutableArray alloc]init];

【讨论】:

【解决方案2】:

我相当肯定你不能在枚举期间更改可变对象。

这个 SO 问题可能会有所帮助:Setting an object during fast enumeration problems

【讨论】:

  • 你是对的,但这不是他收到的例外。所以 +1 在他听了@Ramy 之后预测他的下一个 SO 问题
【解决方案3】:

在您的 init 方法中,输入:

budgetArray = [[NSMutableArray alloc] init];

另外,为什么不使用字典和数组字面量语法?

-(void)applyCCCSWeights {
    NSMutableDictionary *valueDict;
    NSString *newAmount;

    for (NSDictionary *budgetElement in [self budgetArray]) {
        valueDict = [budgetElement mutableCopy];
        newAmount = [NSString stringWithFormat:@"%0.2f", [[self afterTaxIncome].text floatValue] * [budgetElement[@"cccs_weight"] floatValue]];
        valueDict[@"amount"] = newAmount;

        _budgetArray[0] = valueDict;
        NSLog(@"%0.2f (%0.2f)", [budgetElement[@"amount"] floatValue], [[self afterTaxIncome].text floatValue] * [budgetElement[@"cccs_weight"] floatValue]);
    }

    [self.budgetTableView reloadData];
}

注意[[self budgetArray] replaceObjectAtIndex:0 withObject:valueDict];

变成:_budgetArray[0] = valueDict;

【讨论】:

  • 感谢大家的帮助。我的最终解决方案是使用上述方法和本地“NSMutableArray *tempArray”来保存新值,最后: self.budgetArray = [[NSMutableArray alloc] initWithArray:tempArray]; [self.budgetTableView reloadData];
  • 见上面的评论。阅读 NSJSONSerialization 文档。
【解决方案4】:

在对数组进行快速迭代时不能更改数组。另一方面,这完全没有必要。该代码绝对低效:只需制作数组 NSMutableDictionaries 的元素,然后直接更改字典,而不是创建副本然后更改副本中的元素。

后来注意到你使用了NSJSONSerialization;看flag,不要盲目传0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    相关资源
    最近更新 更多