2013-06-01 4 views
1

Я создал простую базу данных и поместил в NSUserDefaults. Моя база данных NSMutableArray, в которой есть словари и массивы. Когда я создаю NSMutableArray из NSUSerDefaults, я не могу добавить никаких объектов в мои изменяемые объекты внутри моего NSMutableArray. Вот мой код:Mutable Objects внутри NSUserDefaults

NSMutableArray *arrayOne = [NSMutableArray arrayWithContentsOfFile:[self createEditableCopyOfIfNeededWithFileName:@"Form.plist"]]; 

NSUserDefaults *ayarlar = [NSUserDefaults standardUserDefaults]; 

[ayarlar setObject:arrayOne forKey:@"form"]; 

NSMutableArray *arrayTwo = [NSMutableArray arrayWithArray:[[ayarlar objectForKey:@"form"] mutableCopy]]; 

[[[arrayTwo objectAtIndex:0] objectForKey:@"itemlar"] addObject:@"hop"]; 

А вот ошибка:

'NSInternalInconsistencyException', причина: '- [__ NSCFArray insertObject: atIndex]: метод мутирует отправлен неизменного объекта'

Как я могу сделать эту работу? Всем спасибо.

+0

Пожалуйста, проверьте мой ответ, это может вам помочь. – Nirav

ответ

4

NSUserDefaults - это неправильное место для хранения ваших данных. Прежде всего, его следует использовать только для очень небольших объемов данных, таких как настройки. А во-вторых, он всегда возвращает неизменяемые объекты, даже если вы установите mutable. Создание изменчивой копии вашего первого массива не помогает, потому что только массив будет изменяться. Все, что находится внутри этого массива, не тронуто методом mutableCopy и остается неизменным.

Вы должны использовать класс NSPropertyListSerialization для чтения и записи ваших данных из файла. При чтении вы можете передавать параметры, управляющие изменчивостью прочитанных объектов. Там вы захотите передать NSPropertyListMutableContainers или NSPropertyListMutableContainersAndLeaves.

Сперва все ваши контейнеры (массивы и словари, которые есть) будут изменчивыми. С последними также листья (то есть объекты NSString и NSData) будут изменчивыми.

В зависимости от того, насколько большой может быть ваш набор данных, вы, вероятно, должны использовать настоящую базу данных или базовые данные.

2

NSUserDefaults никогда не возвращает изменчивые объекты.

Ваш код выполняет каждый способ создания изменяемого массива, о котором вы можете думать (т. Е. Вы создаете изменяемую копию того, что вы только что создали изменчивую копию), но вы имеете дело только с корневым контейнером item - не внутренние/листовые предметы. Итак, когда вы делаете objectForKey:@"itemlar"] на свой изменяемый массив, вы возвращаете неизменный объект обратно.

Чтобы заставить его работать, вам нужно написать свой собственный метод, который выполняет итерации и рекурсирует через массив, создавая изменяемые копии на всех уровнях.

В качестве альтернативы вы можете посмотреть сторонний вариант, например this, который выкапывает под капотом NSUserDefaults для генерации изменяемых контейнеров.

+0

вы красоты. Ваш код github работал как шарм. Спасибо –

2

NSUserDefaults, и списки свойств в целом, не записывают изменчивость. Когда объект заново создается из файла, он может быть сконструирован либо как изменяемый, либо неизменяемый объект (для типов, у которых есть опция, например массивы). К сожалению, NSUserDefaults не дает вам вызова API для непосредственного получения неизменяемого объекта.

У вас есть два варианта: (a) создать измененную копию объекта, возвращаемого NSUserDefaults, или (b) сохранить объект самостоятельно в качестве списка свойств в отдельном файле - таким образом вы можете прочитать его обратно как изменяемый напрямую.

Для (b) прочитано Apple's docs - показано, как обрабатывается изменчивость.

1

Вы можете напрямую с использованием метода insertObject.

На месте

[[[arrayTwo objectAtIndex:0] objectForKey:@"itemlar"] addObject:@"hop"]; 

использования этого

[arrayTwo insertObject:@"hop" atIndex:0]; 

Это будет работать, как я испытал это также работает FinR после того, что вы можете сделать это как непреложный объект как NSARRAY и сохранить его до NSUSERDEFAULTS.

+0

Что делать, если индекс: 0 не пуст? –

+0

, если у вас есть два объекта в массиве, например {@ "1", @ "2"}, а затем, если вы добавите один объект, например @ "hop", в индекс 0. Он добавит этот объект по индексу/позиции 0. – Nirav

+0

Я сделал это. он будет работать как стек. – Nirav

Смежные вопросы