Skip to content
This repository was archived by the owner on Aug 17, 2023. It is now read-only.
This repository was archived by the owner on Aug 17, 2023. It is now read-only.

Optional scalar attributes extension #10

Description

@mgratzer

https://aplus.rs/2017/handling-core-data-optional-scalar-attributes/

Extension proposal from latest project

  • Think about using KeyPath instead of stringified parameters
public extension NSManagedObject {

    // RawRepresentable [String]? Transformable

    func valueFromPrimitives<T>(name: String) -> [T]? where T: RawRepresentable, T.RawValue == String {
        let primitive: [String]? = getPrimitiveValues(name: name)
        return primitive?.compactMap { T(rawValue: $0) }
    }

    func setPrimitivesFrom<T>(_ value: [T]?, name: String) where T: RawRepresentable, T.RawValue == String  {
        setPrimitiveValues(value?.map { $0.rawValue }, name: name)
    }
    
    // RawRepresentable String?

    func valueFromPrimitive<T>(name: String) -> T? where T: RawRepresentable, T.RawValue == String {
        let primitive: String? = getPrimitiveValue(name: name)
        return primitive.flatMap { T(rawValue: $0) }
    }

    func setPrimitiveFrom<T>(_ value: T?, name: String) where T: RawRepresentable, T.RawValue == String  {
        setPrimitiveValue(value?.rawValue, name: name)
    }

    // String?

    func valueFromPrimitive(name: String) -> String? {
        let primitive: String? = getPrimitiveValue(name: name)
        return primitive
    }

    func setPrimitiveFrom(_ value: String?, name: String) {
        setPrimitiveValue(value, name: name)
    }
    
    // Double?

    func valueFromPrimitive(name: String) -> Double? {
        let primitive: NSNumber? = getPrimitiveValue(name: name)
        return primitive?.doubleValue
    }

    func setPrimitiveFrom(_ value: Double?, name: String) {
        let primitive = value.flatMap { NSNumber(value: $0) }
        setPrimitiveValue(primitive, name: name)
    }

    // Int?

    func valueFromPrimitive(name: String) -> Int? {
        let primitive: NSNumber? = getPrimitiveValue(name: name)
        return primitive?.intValue
    }

    func setPrimitiveFrom(_ value: Int?, name: String) {
        let primitive = value.flatMap { NSNumber(value: $0) }
        setPrimitiveValue(primitive, name: name)
    }
    
    // Int32?
    
    func valueFromPrimitive(name: String) -> Int32? {
        let primitive: NSNumber? = getPrimitiveValue(name: name)
        return primitive?.int32Value
    }

    func setPrimitiveFrom(_ value: Int32?, name: String) {
        let primitive = value.flatMap { NSNumber(value: $0) }
        setPrimitiveValue(primitive, name: name)
    }

    // Int64?

    func valueFromPrimitive(name: String) -> Int64? {
        let primitive: NSNumber? = getPrimitiveValue(name: name)
        return primitive?.int64Value
    }

    func setPrimitiveFrom(_ value: Int64?, name: String) {
        let primitive = value.flatMap { NSNumber(value: $0) }
        setPrimitiveValue(primitive, name: name)
    }
    
    // Bool?

    func valueFromPrimitive(name: String) -> Bool? {
        let primitive: NSNumber? = getPrimitiveValue(name: name)
        return primitive?.boolValue
    }

    func setPrimitiveFrom(_ value: Bool?, name: String) {
        let primitive = value.flatMap { NSNumber(value: $0) }
        setPrimitiveValue(primitive, name: name)
    }
    
    // To-Many Relations

    func getRelationships<T: NSManagedObject>(name: String) -> [T] {
        willAccessValue(forKey: name)
        defer { didAccessValue(forKey: name) }

        let values = primitiveValue(forKey: name) as? NSSet
        return values?.compactMap { $0 as? T } ?? []
    }

    func setRelationships<T: NSManagedObject>(name: String, value: [T]) {
        willChangeValue(forKey: name)
        defer { didChangeValue(forKey: name) }

        let primitive = NSMutableSet()
        primitive.addObjects(from: value)
        setPrimitiveValue(primitive, forKey: name)
    }

    // To-Many Relations

    func getOrderedRelationships<T: NSManagedObject>(name: String) -> [T] {
        willAccessValue(forKey: name)
        defer { didAccessValue(forKey: name) }

        let values = primitiveValue(forKey: name) as? NSOrderedSet
        return values?.compactMap { $0 as? T } ?? []
    }

    func setOrderedRelationships<T: NSManagedObject>(name: String, value: [T]) {
        willChangeValue(forKey: name)
        defer { didChangeValue(forKey: name) }

        let primitive = NSMutableOrderedSet()
        primitive.addObjects(from: value)
        setPrimitiveValue(primitive, forKey: name)
    }
    
    // Helper

    private func getPrimitiveValue<T>(name: String) -> T? {
        willAccessValue(forKey: name)
        defer { didAccessValue(forKey: name) }
        return primitiveValue(forKey: name) as? T
    }

    private func setPrimitiveValue<T>(_ value: T?, name: String) {
        willChangeValue(forKey: name)
        defer { didChangeValue(forKey: name) }
        setPrimitiveValue(value, forKey: name)
    }
    
    // Transformable
    
    private func getPrimitiveValues<T>(name: String) -> [T]? {
        willAccessValue(forKey: name)
        defer { didAccessValue(forKey: name) }
        return primitiveValue(forKey: name) as? [T]
    }

    private func setPrimitiveValues<T>(_ value: [T]?, name: String) {
        willChangeValue(forKey: name)
        defer { didChangeValue(forKey: name) }
        setPrimitiveValue(value, forKey: name)
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions