Подтвердить что ты не робот

CoreData - не может установить пустую строку как значение по умолчанию для атрибута

У меня есть объект в моем datamodel со строковым атрибутом, который в настоящее время является необязательным, и я хотел бы преобразовать его в требуемый атрибут со значением по умолчанию пустой строки.

Как выяснили другие, оставив значение по умолчанию пустым в модуле данных Xcode CoreData, возникают ошибки проверки (поскольку разработчик интерпретирует это как NULL), но при попытке '', "или @" в качестве значения по умолчанию в этих буквальных символах интерпретируется как значение по умолчанию, а не пустая строка нулевой длины, по желанию.

Я нашел этот поток в Google, однако, помимо того, что решение было действительно уродливым (определение модели разделено между .xcdatamodel и objc-источником), оно также не работает работа для облегченных миграций, потому что эти миграции выполняются исключительно на основе файлов .xcdatamodel, а логика objc из ваших реализаций объекта не загружается.

Есть ли способ достичь этого в дизайнере модели данных?

4b9b3361

Ответ 1

Это очень интересный вопрос. После некоторого тестирования я не думаю, что это возможно из-за того, как настроено текстовое поле в модели данных.

В принципе, вы можете использовать символ unicode с пустым множеством \u2205 для представления пустой строки по умолчанию, но текстовое поле, похоже, не принимает никаких экранов, поэтому оно преобразует любую попытку избежать символьного кода юникода в литерал строка символов кода, например ввод '\ u2205' заканчивается как буквальный текст '\ u2205'.

В теории вы можете написать приложение-утилиту для чтения в графически создаваемом файле модели управляемых объектов, а затем программным образом установить атрибут по умолчанию равным пустой строке, а затем сохранить файл обратно на диск. Я говорю "теоретически", потому что нет документального способа сохранения файла модели управляемого объекта из кода. Вы можете прочитать его и изменить его в памяти, но не сохранять изменения.

Немного надзора, я думаю.

Я не думаю, что у вас есть выбор, кроме как прагматически задавать пустую строку по умолчанию при первой загрузке модели. Это просто сделать, но это уродливо, и вам придется помнить, что вы это сделали (особенно если вы переносите версии), но я думаю, что сейчас это единственный выбор.

Ответ 2

Выньте свой любимый редактор XML (я только что использовал Emacs) и погрузитесь в файл contents внутри пакета .xcdatamodel внутри пакета .xcdatamodeld. Затем просто добавьте атрибут defaultValueString="" XML в элемент <attribute>...</attribute> внутри скобок <entity>...</entity>. Вот пример:

<attribute name="email" attributeType="String" defaultValueString="" syncable="YES"/>

Я не могу говорить о том, выживает ли это миграция, так как мне еще не приходилось это делать.

Ответ 3

Я решил это, переопределив getter для моего поля - если он содержит null, вместо этого я возвращаю пустую строку:

-(NSString *)unit {
    if ([self primitiveValueForKey:@"unit"] == NULL) {
        return @"";
    } else {
        return [self primitiveValueForKey:@"unit"];
    }
}

Пока это похоже на трюк, и я бы предположил, что это не повлияет на миграцию (хотя я не знаю достаточно о них, чтобы точно сказать). Мне все равно, есть ли нуль или пустая строка в db, в конце концов - до тех пор, пока я получаю "вместо", когда запрашиваю поле.

Ответ 4

Мой подход к решению этой проблемы заключался в создании подкласса NSManagedObject и обработки подстановки пустых строк для значений NULL в awakeFromInsert. Затем я устанавливаю все сущности как дочерние элементы этого подкласса, а не дочерние элементы NSManagedObject. Предположение здесь состоит в том, что я хочу, чтобы по умолчанию атрибут каждый в пределах заданного объекта был установлен на пустую строку по умолчанию (он не работает или, по крайней мере, потребует дополнительной логики, если вы хотите, чтобы некоторые остаются NULL в пределах одного и того же объекта).

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

- (void)awakeFromInsert {
    [super awakeFromInsert];

    NSDictionary *allAttributes = [[self entity] attributesByName];
    NSAttributeDescription *oneAttribute;

    for (NSString *oneAttributeKey in allAttributes) { 
        oneAttribute = [allAttributes objectForKey:oneAttributeKey];
        if ([oneAttribute attributeType] == NSStringAttributeType) {
            if (![self valueForKey:[oneAttribute name]]) {
                [self setValue:@"" forKey:[oneAttribute name]];
            }
        }
    }
}

Ответ 5

Вы можете сделать это вручную. В вашем классе модели переопределите awakeFromInsert и установите строки в пустую строку

Swift:

override func awakeFromInsert()
{
    super.awakeFromInsert()
    self.stringProperty = ""
}

Objective-C

- (void) awakeFromInsert
{
    [super awakeFromInsert];
    self.stringProperty = @"";
}

Ответ 6

Вот решение Swift, основанное на ответе Дэвида Раветти и комментарий edelaney05. Кроме того, я добавил проверку доступности.

Это решение отлично работает в моих проектах.

class ExampleEntity: NSManagedObject {

    ...

    override func awakeFromInsert() {
        super.awakeFromInsert()
        for (key, attr) in self.entity.attributesByName {
            if attr.attributeType == .stringAttributeType && !attr.isOptional {
                if self.value(forKey: key) == nil {
                    self.setPrimitiveValue("", forKey: key)
                }
            }
        }
    }

    ...
}

Ответ 7

Более простое решение, основанное на ответе Скотта Маркса, позволяет избежать синтаксических ошибок:

Во-первых, временно установите значение по умолчанию, чтобы его было легко найти, что-то вроде того, что here you are. Откройте в любом текстовом редакторе файл contents внутри пакета .xcdatamodel внутри пакета .xcdatamodeld. Затем просто выполните поиск с заменой строки "here you are" на "" в этом файле.

Миграция прошла без проблем.

Ответ 8

Может быть, я опоздал с этим ответом, но я был в Google и нашел этот форум.

Решение очень простое:

  1. При нажатии на xcdatamodelId (на левом экране)
  2. Изменить вид сущности на график
  3. Дважды щелкните любой атрибут, который вы хотите, и меню появится справа.

Все изменения просты.

Часть 2

For Part 2

Часть 3

For Part 3