Мой сегментированный сборщик имеет нормальные значения Int в виде тегов. Как это передается в CoreData и из него?

В моем средстве выбора сегментированных элементов управления SwiftUI для выбора используются простые значения Int ".tag(1)" и т. Д.

CoreData имеет только варианты Int16, Int32 и Int64 на выбор, и с любым из этих вариантов кажется, что мой выбор выбора и CoreData отказываются общаться друг с другом.

Как достигается эта (?? простая??) задача?

Я пробовал все числовые опции в CoreData, включая Int16-64, double и float, все они ломают мой код или просто не работают.

Picker(selection: $addDogVM.gender, label: Text("Gender?")) {
    Text("Boy ♂").tag(1)
    Text("?").tag(2)
    Text("Girl ♀").tag(3)
}

Я ожидал, что любой из 3 вариантов CoreData Int будет работать из коробки и будет совместим со (стандартным) Int, используемым средством выбора.

1 ответ

Решение

Каждый элемент сегментированного элемента управления представлен индексом типа Int, поэтому этот индекс начинается с 0.

Итак, используя ваш пример сегментированного элемента управления с тремя сегментами (например: Boy ♂,?, Girl ♀), каждый сегмент представлен тремя индексами 0, 1 и 2.

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

segmentedControl.selectedSegmentIndex = 2

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

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

Итак, чтобы продолжить:

В документации Apple указано, что...

... на 64-битных платформах Int имеет тот же размер, что и Int64.

Итак, в редакторе модели Core Data (.xcdatamodeld файл), я решаю применить Integer 64 тип атрибута для любого значения, которое будет использоваться как Int в моем коде.

Также где-то некоторое время назад я читал, что если нет причин использовать Integer 16 или Integer 32, затем по умолчанию используется Integer 64в графе объектной модели. (Я предполагаюInteger 16 или Integer 32 сохранены для обратной совместимости.) Если я найду эту ссылку, я свяжу ее здесь.

Я мог бы написать здесь об использовании скалярных типов атрибутов и вручную написать подклассы управляемых объектов, выбрав в инспекторе атрибутов Class Codegen = Manual/None, но, честно говоря, я решил, что такие дополнительные детали только усложнят ситуацию.

Таким образом, подкласс / а управляемого объекта "автоматически сгенерированный Core Data" (NSManagedObject) будет использовать необязательный NSNumber? обертка...

Поэтому вам нужно будет преобразовать ваши постоянные / сохраненные данные в свой код.

Я делаю это в двух местах... когда я обращаюсь к данным и когда сохраняю их.

(Отмечая, что я предполагаю, что ваша сущность имеет тип Dog и существует экземпляр dog т.е. let dog = Dog())

// access
tempGender = dog.gender as? Int

// save
dog.gender = tempGender as NSNumber?

В промежутках я использую "временную" var свойство типа Int работать с сегментированным контролем.

// temporary property to use with segmented control
private var tempGender: Int?

ОБНОВИТЬ

Теперь я делаю последнюю часть немного по-другому...

Вместо того, чтобы преобразовывать данные в код, я сделал простое расширение подкласса управляемого объекта, чтобы выполнить преобразование. Поэтому вместо того, чтобы напрямую обращаться к атрибуту Core Data и манипулировать данными в коде, теперь я использую эту удобную var.

extension Dog {
    var genderAsInt: Int {
        get {
            guard let gender = self.gender else { return 0 }
            return Int(truncating: gender)
        }
        set {
            self.gender = NSNumber(value: newValue)
        }
    }
} 

Ваш код сборщика...

Picker(selection: $addDogVM.genderAsInt, label: Text("Gender?")) {
    Text("Boy ♂").tag(0)
    Text("?").tag(1)
    Text("Girl ♀").tag(2)
}

Есть вопросы, задавайте в комментариях.

Другие вопросы по тегам