Xcode 8 iOS 10 — NSMutableDictionary выдает — «мутирующий метод, отправленный в неизменяемый объект»

#ios #objective-c #xcode

#iOS #objective-c #xcode

Вопрос:

У меня есть словарь NSMutable, который я предварительно загружаю для редактирования сохраненной оценки (сохраненной в UserDefaults). eParts хранится в другом NSMutableDictionary под названием «оценка», разбивка которого выглядит следующим образом:

 if ([appDefaults objectForKey:@"selectedEstimate"]) {
    estimate = [[NSMutableDictionary alloc]initWithDictionary:[[appDefaults objectForKey:@"selectedEstimate"] mutableCopy] copyItems:YES];
    eParts = [[NSMutableDictionary alloc] initWithDictionary:[[estimate objectForKey:@"eParts"] mutableCopy] copyItems:YES];
    eRniParts = [[NSMutableDictionary alloc]initWithDictionary:[[estimate objectForKey:@"eRniParts"] mutableCopy] copyItems:YES];
    matrix = [[estimate objectForKey:@"matrix_id"] intValue];
    company = [[db getBodyshop:[[estimate objectForKey:@"company_id"] intValue]] mutableCopy];
    vehicle = [[estimate objectForKey:@"vehicle"] mutableCopy];
    otherParts = [[NSMutableArray alloc] initWithArray:[estimate objectForKey:@"otherParts"] copyItems:YES];
    NSLog(@"other parts now contains: %@",otherParts);
} else {
    estimate = [[NSMutableDictionary alloc] init];
    eParts = [[NSMutableDictionary alloc] init];
    eMiscParts = [[NSMutableDictionary alloc] init];
    eRniParts = [[NSMutableDictionary alloc] init];
    otherParts = [[NSMutableArray alloc] init];
    matrix = [[appDefaults objectForKey:@"selectedMatrix"] intValue];
    company = [[NSMutableDictionary alloc] initWithDictionary:[[appDefaults objectForKey:@"autobodyCompany"] mutableCopy] copyItems:YES];
    vehicle = [[NSDictionary alloc] initWithDictionary:[[appDefaults objectForKey:@"vehicle"] mutableCopy] copyItems:YES];
    [estimate setObject:[vehicle mutableCopy] forKey:@"vehicle"];
}


    Printing description of self->estimate:
{
    address = "1818 University Ave NE";
    city = "Somewhere Else";
    "company_id" = 1;
    "company_name" = "Abco Autobody";
    "contact_name" = "Mike Peterson";
    date = "10-04-2016";
    eParts =     {
        Liftgate =         {
            bodyshop = 0;
            "bs_price" = "Body Shop";
            "dent_size" = DIME;
            "entry_id" = 6;
            "estimate_id" = 5;
            "off_matrix" = 0;
            "off_matrix_price" = "(null)";
            oversized = 1;
            "oversized_quantity" = "";
            "part_name" = Liftgate;
            quantity = "1-5";
            type = NRML;
        };
    };
    email = "mikep@abcoautobody.com";
    "estimate_id" = 5;
    "grand_total" = "95.00";
    invoiced = 0;
    "matrix_id" = 0;
    paid = 0;
    phone = "651-555-4321";
    state = MN;
    vehicle =     {
        agency = "";
        "claim_number" = "";
        "estimate_id" = 5;
        make = chevrolet;
        model = "silverado 1500";
        plate = "";
        "repair_order_number" = "";
        submodel = "double cab";
        "vehicle_id" = 6;
        vin = 1GCVKREC4FZ221600;
        year = 2015;
    };
    zip = 55421;
}


    eParts = [[NSMutableDictionary alloc] initWithDictionary:[[[appDefaults objectForKey:@"estimate"] objectForKey:@"eParts"] mutableCopy] copyItems:YES];
  

затем, когда я пытаюсь удалить элемент из изменяемого словаря:

     [[estimate objectForKey:@"eParts"] removeObjectForKey:tempPartName];
  

он выдает:

     *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** First throw call stack:
(0x184a281c0 0x18346055c 0x184a28108 0x184913a5c 0x10005e3ec 0x100062188 0x10005d05c 0x18a89f7b0 0x18a89f730 0x18a889be4 0x18a89f01c 0x18ae2ff30 0x18ae2bfc8 0x18ae2bae8 0x18ae2ada4 0x18a899d70 0x18a86a858 0x18b057cb8 0x18b051720 0x1849d6278 0x1849d5bc0 0x1849d37c0 0x184902048 0x186385198 0x18a8d5628 0x18a8d0360 0x10007d00c 0x1838e45b8)
libc  abi.dylib: terminating with uncaught exception of type NSException
  

Это не было проблемой до Xcode 8 и iOS 10… любая помощь будет высоко оценена!

Заранее спасибо.

Комментарии:

1. вы инициализируете eParts , но пытаетесь удалить estimate .

2. Как вы создаете / извлекаете estimate словарь?

3. Я обновил сообщение, включив в него информацию о «оценке»

4. Можете ли вы показать, что присваивается estimate переменной?

5. objectForKey всегда возвращает неизменяемый объект. Вызовите mutableCopy , чтобы сделать его изменяемым.

Ответ №1:

Просто попробуйте это

На самом деле, вы можете сделать это с помощью convert с deepCopy помощью .

 if ([appDefaults objectForKey:@"selectedEstimate"]) {

    estimate = [[NSMutableDictionary alloc]initWithDictionary:[[appDefaults objectForKey:@"selectedEstimate"] mutableCopy] copyItems:YES];
    estimate = (NSMutableDictionary *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)estimate, kCFPropertyListMutableContainers));

    eParts = [estimate objectForKey:@"eParts"];
    eRniParts = [estimate objectForKey:@"eRniParts"];
    matrix = [[estimate objectForKey:@"matrix_id"] intValue];
    company = [[db getBodyshop:[[estimate objectForKey:@"company_id"] intValue]] mutableCopy];
    vehicle = [estimate objectForKey:@"vehicle"];
    otherParts = [estimate objectForKey:@"otherParts"];
    NSLog(@"other parts now contains: %@",otherParts);

    } else {
        estimate = [[NSMutableDictionary alloc] init];
        eParts = [[NSMutableDictionary alloc] init];
        eMiscParts = [[NSMutableDictionary alloc] init];
        eRniParts = [[NSMutableDictionary alloc] init];
        otherParts = [[NSMutableArray alloc] init];
        matrix = [[appDefaults objectForKey:@"selectedMatrix"] intValue];
        company = [[NSMutableDictionary alloc] initWithDictionary:[[appDefaults objectForKey:@"autobodyCompany"] mutableCopy] copyItems:YES];
        vehicle = [[NSDictionary alloc] initWithDictionary:[[appDefaults objectForKey:@"vehicle"] mutableCopy] copyItems:YES];
        [estimate setObject:[vehicle mutableCopy] forKey:@"vehicle"];
    }
  

После этого дайте мне знать, работает он или нет!!

Надеюсь, это вам поможет.

Счастливого кодирования!!

Комментарии:

1. Это сработало … Добавление этой строки: оценка = (NSMutableDictionary *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)оценка, kCFPropertyListMutableContainers)); … Спасибо!

2. @CrypTech Studios приветствуется.. вы также должны поддержать мой ответ 😉

Ответ №2:

Преобразуйте ваш объект [оценить objectForKey:@»eParts»] в NSMutableDictionary, а затем попробуйте удалить для ключа tempPartName