1

私の問題はNSMutableArray、ヘッダー ファイルで定義されているタイプのクラス プロパティを持っているにもかかわらず、配列要素の 1 つ ( NSDictionary) を変更しようとすると、次のランタイム エラーが発生することです。

2013-01-16 14:17:20.993 負債 [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上記は単なるプレースホルダーであることに注意してください。これは正しいインデックスに置き換えられます。

4

4 に答える 4

4

budgetArray確かに不変なので、可変に作成する必要があります。

おそらくあなたは次のようなことをしています:

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

そして、コンパイラの警告を無視します。変更可能にします。

budgetArray= [[NSMutableArray alloc]init];
于 2013-01-16T19:33:16.623 に答える
3

列挙中に可変オブジェクトを変更できないことは確かです。

この SO の質問が役立つ場合があります:高速列挙問題中にオブジェクトを設定する

于 2013-01-16T19:54:37.077 に答える
0

あなたの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;

于 2013-01-17T01:57:12.873 に答える
0

配列に対して高速反復を実行している間は、配列を変更できません。一方、それはまったく不要です。コードは完全に非効率的です。コピーを作成してからコピー内の要素を変更するのではなく、配列 NSMutableDictionaries の要素を作成してから辞書を直接変更するだけです。

NSJSONSerialization を使用していることに後で気付きました。フラグを見て、やみくもに 0 を渡さないでください。

于 2014-03-17T00:03:55.070 に答える