Мой сегментированный сборщик имеет нормальные значения 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)
}
Есть вопросы, задавайте в комментариях.