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

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

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

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

Есть ли способ добиться этого в конструкторе модели данных?

Ответы [ 7 ]

30 голосов
/ 01 марта 2011

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

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

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

Я думаю, что это недосмотр.

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

15 голосов
/ 07 апреля 2013

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

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

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

7 голосов
/ 13 марта 2012

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

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

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

6 голосов
/ 21 февраля 2013

Мой подход к решению этой проблемы заключался в создании подкласса 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]];
            }
        }
    }
}
3 голосов
/ 31 декабря 2015

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

Swift:

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

Objective-C

- (void) awakeFromInsert
{
    [super awakeFromInsert];
    self.stringProperty = @"";
}
1 голос
/ 22 сентября 2016

Вот решение 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)
                }
            }
        }
    }

    ...
}
0 голосов
/ 22 мая 2018

Возможно, я опоздал с этим ответом, но я поискал и нашел этот форум.

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

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

Все изменениялегко.

Часть 2

For Part 2

Часть 3

For Part 3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...