IOS рдореЗрдВ рд╕рд░реНрд╡рд░ рдбреЗрдЯрд╛ рдкрд╛рд░реНрд╕рд░ рд▓реЙрдпрд▓реНрдЯреА рдХреЛ рдмрдврд╝рд╛рдирд╛

рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди, рдПрдХ рддрд░рд╣ рд╕реЗ рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп, рд╣рдореЗрдВ рд╕рд░реНрд╡рд░ рдбреЗрдЯрд╛ рдХреЛ рдЖрдВрддрд░рд┐рдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЙрдбрд▓ рдореЗрдВ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЕрдзрд┐рдХрд╛рдВрд╢ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рдбреЗрдЯрд╛ JSON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдЖрддрд╛ рд╣реИред рд╕реНрд╡рд┐рдлреНрдЯ 4 рд╕реЗ рд╢реБрд░реВ рд╣реЛрдХрд░, JSON рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХрд╛ рдореБрдЦреНрдп рдЙрдкрдХрд░рдг рдПрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ DecodableрдФрд░ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ JSONDecoderред


рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдиреЗ рдбреЗрдЯрд╛ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдмрд╣реБрдд рд╕рд░рд▓ рдХрд░ рджрд┐рдпрд╛ рдФрд░ рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЛрдб рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдХрдо рдХрд░ рджрд┐рдпрд╛ред рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рдХреЗрд╡рд▓ JSON рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреА рддрд░рд╣ рдирд╛рдорд┐рдд рдЧреБрдгреЛрдВ рдХреЗ рд╕рд╛рде рдореЙрдбрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдФрд░ JSONDecoderрдЖрдкрдХреЗ рд▓рд┐рдП рдмрд╛рдХреА рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдиреНрдпреВрдирддрдо рдХреЛрдб, рдЕрдзрд┐рдХрддрдо рд▓рд╛рднред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рдХрдореА рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдирд╛рдо рд╣реИ, рдмреЗрд╣рдж рдХрдо рдкрд╛рд░реНрд╕рд░ рдХреА рд╡рдлрд╛рджрд╛рд░реАред рдореЗрдВ рд╕рдордЭрд╛ рджреВрдВрдЧрд╛ред рдпрджрд┐ рдЖрдВрддрд░рд┐рдХ рдбреЗрдЯрд╛ рдореЙрдбрд▓ (Decodable рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕) рдФрд░ JSON рдореЗрдВ рдХреНрдпрд╛ рдЖрдпрд╛, рдХреЗ рдмреАрдЪ рдХреЛрдИ рд╡рд┐рд╕рдВрдЧрддрд┐ рд╣реИ,JSONDecoderрдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрддрд╛ рд╣реИ рдФрд░ рд╣рдо рдкреВрд░реА рд╡рд╕реНрддреБ рдЦреЛ рджреЗрддреЗ рд╣реИрдВред рд╢рд╛рдпрдж, рдХреБрдЫ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ, рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдпрд╣ рдореЙрдбрд▓ рдмреЗрд╣рддрд░ рд╣реИ, рдЦрд╛рд╕рдХрд░ рдЬрдм рдпрд╣ рдЖрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡рд┐рддреНрддреАрдп рд▓реЗрдирджреЗрди рдХреЗ рд▓рд┐рдПред рд▓реЗрдХрд┐рди рдХрдИ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЕрдзрд┐рдХ рд╡рдлрд╛рджрд╛рд░ рдмрдирд╛рдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЕрдкрдиреЗ рдЕрдиреБрднрд╡ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдФрд░ рдЗрд╕ рд╕рдорд╛рди рдирд┐рд╖реНрдард╛ рдХреЛ рдмрдврд╝рд╛рдиреЗ рдХреЗ рдореБрдЦреНрдп рддрд░реАрдХреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ред


рдЕрдорд╛рдиреНрдп рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдирд╛


рдареАрдХ рд╣реИ, рдкрд╣рд▓реА рд╡рд╕реНрддреБ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЕрдорд╛рдиреНрдп рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЫрд╛рди рд░рд╣реА рд╣реИред рдХрдИ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ, рдпрджрд┐ рдХреЛрдИ рдиреЗрд╕реНрдЯреЗрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдорд╛рдиреНрдп рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдо рд╕рдВрдкреВрд░реНрдг рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдЦреЛрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рдПрдХрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдФрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд╕рд░рдгрд┐рдпреЛрдВ рджреЛрдиреЛрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред рдореИрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреВрдВрдЧрд╛ред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдо рд╕рд╛рдорд╛рди рдмреЗрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡реЗрджрди рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╕реНрдХреНрд░реАрди рдкрд░ рд╣рдореЗрдВ рд▓рдЧрднрдЧ рдЗрд╕ рд░реВрдк рдореЗрдВ рд╕рд╛рдорд╛рдиреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдорд┐рд▓рддреА рд╣реИред


{
    "products": [
       {...},
       {...},
       ....
    ]
}

, . . , , - . , JSONDecoder тАЬ тАЭ .


, :


{
    "id": 1,
    "title": "Awesome product",
    "price": 12.2,
    "image": {
        "id": 1,
        "url": "http://image.png",
        "thumbnail_url": "http://thumbnail.png"
    }
}

, , image. , , image , image = nil. , , JSONDecoder .


, JSONDecoder 2 : decode decodeIfPresent. optional , nil, , null. .


, , . , init(decoder) try? nil. , boilerplate . .


struct FailableDecodable<Value: Decodable>: Decodable {

    var wrappedValue: Value?

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        wrappedValue = try? container.decode(Value.self)
    }
}

struct FailableDecodableArray<Value: Decodable>: Decodable {

    var wrappedValue: [Value]

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        var elements: [Value] = []
        while !container.isAtEnd {
            if let element = try? container.decode(Value.self) {
                elements.append(element)
            }
        }
        wrappedValue = elements
    }
}

.


struct ProductList: Decodable {
    var products:FailableDecodableArray<Product>
}

struct Product: Decodable {
    let id: Int
    let title: String
    let price: Double
    let image: FailableDecodable<Image>?
}

struct Image: Decodable {
    let id: Int
    let url: String
    let thumbnailUrl: String
}

. , .


let products = productsList.products.wrappedValue
let image = products.first?.image.wrappedValue

FailableDecodableArray . , RandomAccessCollection MutableCollection , wrappedValue. FailableDecodable . , , computed property , , . , .


@propertyWrapper


Swift 5.1 тАФ @propertyWrapper.


@propertyWrapper
struct FailableDecodable<Value: Decodable>: Decodable {
    ...
}

@propertyWrapper
struct FailableDecodableArray<Value: Decodable>: Decodable {
    ...
}


struct ProductList: Decodable {
    @FailableDecodableArray
    var products:[Product]
}

struct Product: Decodable {
    let id: Int
    let title: String
    let price: Double
    @FailableDecodable
    let image:Image?
}

, wrappedValue . , , , , :)


, , optional.


@FailableDecodable
let image:Image?


let image: FailableDecodable<Image>

, optional Image? , wrappedValue optional , .
Swift


@FailableDecodable?
let image:Image?

, , JSON nil . @propertyWrapper , 100% JSON.


@dynamicMemberLookup


dynamicMemberLookup.


@dynamicMemberLookup
struct FailableDecodable<Value: Decodable>: Decodable {
    var wrappedValue: Value?

    subscript<Prop>(dynamicMember kp: KeyPath<Value, Prop>) -> Prop {
        wrappedValue[keyPath: kp]
    }

    subscript<Prop>(dynamicMember kp: WritableKeyPath<Value, Prop>) -> Prop {
            get {
                wrappedValue[keyPath: kp]
            }

            set {
                wrappedValue[keyPath: kp] = newValue
            }
    }
}

2 subscript, readonly , read/write . .


struct ProductList: Decodable {
    var products:FailableDecodableArray<Product>
}

struct Product: Decodable {
    let id: Int
    let title: String
    let price: Double
    let image: FailableDecodable<Image>?
}

@propertyWrapper wrappedValue, .


let imageURL = products.first?.image.url

, optional . , , wrappedValue, , .


products.first?.image.load() // Compilation error
products.first?.image.wrappedValue.load() // Success

( ), .



тАФ . - , ( JSON) Swift , тАЬ1тАЭ 1 тАФ . JSONDecoder , , . . , Product .


{
    "id": 1,
    "title": "Awesome product",
    "price": "12.2",
    "image": {
        "id": 1,
        "url": "http://image.png",
        "thumbnail_url": "http://thumbnail.png"
    }
}

, , , тАФ , , , , , . , .


struct Convertible<Value: Decodable & LosslessStringConvertible>: Decodable {
    var wrappedValue: Value
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        guard let stringValue = try? container.decode(String.self),
            let value = Value(stringValue) else {
                wrappedValue = try container.decode(Value.self)
                return
        }
        wrappedValue = value
    }
}

struct Product: Decodable {
    let id: Int
    let title: String
    let price: Convertible<Double>
    let image: FailableDecodable<Image>?
}

, . FailableDecdable @propertyWrapper @dynamicMemberLookup .


( ) . , , API - , , - . , , , , -, , , -, , . , , .


struct StringConvertible: Decodable {
    var wrappedValue: String
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        guard let number = try? container.decode(Double.self) else {
            wrappedValue = try container.decode(String.self)
            return
        }
        wrappedValue = "\(number)"
    }
}

рдЙрдкрд░реЛрдХреНрдд рд╕рднреА рдХреЛ рд╕рд╛рд░рд╛рдВрд╢рд┐рдд рдХрд░рддреЗ рд╣реБрдП, рдореИрдВ рдпрд╣ рдиреЛрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ Decodableрд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдЙрджреНрднрд╡ рдиреЗ JSONDecoderрд╣рдорд╛рд░реЗ рдЬреАрд╡рди рдХреЛ рд╕рд░реНрд╡рд░ рдбреЗрдЯрд╛ рдХреЗ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ, рдЬреЛ рд╣рдорд╛рд░реЗ рдЬреАрд╡рди рдХреЛ рдХрд╛рдлреА рд╕рд░рд▓ рдмрдирд╛ рджрд┐рдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ JSONDecoderрдЗрд╕ рд╕рдордп рдЗрд╕рдХреА рдмрд╣реБрдд рдХрдо рдирд┐рд╖реНрдард╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП (рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ) рдЖрдкрдХреЛ рдереЛрдбрд╝рд╛ рдХрд╛рдо рдХрд░рдиреЗ рдФрд░ рдХреБрдЫ рд░реИрдкрд░ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЗрди рд╕рднреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рд╡рд╕реНрддреБ рдореЗрдВ рд╣реА рдорд╣рд╕реВрд╕ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ JSONDecoder, рдХреНрдпреЛрдВрдХрд┐ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдпрд╣ рднреА рдирд╣реАрдВ рдкрддрд╛ рдерд╛ рдХрд┐ рдХреИрд╕реЗ snakecase рд╕реЗ рдХреИрдорд▓рдХреЗрд╕ рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рддрд╛рд░реАрдЦ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП, рдФрд░ рдЕрдм рдпрд╣ рд╕рдм "рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░" рдЙрдкрд▓рдмреНрдз рд╣реИред


All Articles