Swift Encodable, Decodable Vs Codable - swift

Found in Apple doc, that Codable protocol is composed of Encodable and Decodable. Thus,
Codable = Encodable & Decodable
Now, let's say I implemented below classes,
class X: Codable {
var name: String
}
class Y: Encodable, Decodable {
var name: String
}
class Z: Encodable & Decodable {
var name: String
}
So, is there any functional difference among the classes, X, Y and Z?
If there is no deference why can't we use & in the places of ,?

No there isn't any difference , Codable is a typealias for Encodable & Decodable , so it combines the 2 protocols you're free to use any way
In Swift & is the same as , in protocol composition so Encodable, Decodable = Encodable & Decodable = Codable

Don't think so. Codable means they can be decoded from and encoded into another representation. Decodable means it can be decoded, but not encoded. And encodable is the opposite of that.

They are functionally the same but you can do things with the & syntax that you can't with a comma separated list. Neither of these would work with the comma approach.
public typealias Codable = Decodable & Encodable
func doSomething(with item: ProtocolA & ProtocolB) {
}

Encoding
The process of converting your custom type instances to other representation such as JSON and pList is known as Encoding or Serialization. For encoding, custom types conform to Encodable protocol.
Decoding
The process of converting data in representation such as JSON or pList to instance of your custom type is known as Decoding or Deserialization. For decoding, custom types conform to Decodable protocol.
Codable
To support both encoding and decoding, custom types can conform to Codable protocol which conforms to both Encodable and Decodable.
to Read more about Codable, Decoding and Encoding Click on the this Link

Related

A Struct is codable, it means all of it's properties are codable?

As i understand, if a struct is codable, all properties of the struct are codable.
I tried to encode an object of type PKDrawing (it's a struct in PencilKit), the type is codable, so there are no problem:
PKDrawing : Codable
And then i tried to encode a property of this object in type PKStroke
let drawing1JSON = try? JSONEncoder().encode(stroke)
but there are an error "PKStroke need to conform to Encodable"
Do i have misunderstood?
and there a a way that i can encode PKStroke without implement codable manualy?

Can typealias be Codable?

I have a root object that consists mainly of an array of tuples and then a bunch of state enums. The tuples are described this way:
typealias Program = [(Number, Statement)]
The root object is currently NSCoding, but I'd like to add Codable to make the switch to JSON. In most cases, making the various parts become Codable requires nothing more than adding , Codable to their declarations, but that's not working for the tuples. I think this is just a syntax issue, but neither of these work:
typealias Program, Codable = [(Number, Statement)]
typealias Program = [(Number, Statement)], Codable
Is this possible? The horrible documentation only mentions typealias when describing the protocol itself, and perhaps my Google-fu is failing, but I'm not seeing cogent references here on SO.
UPDATE: root object(s):
typealias Program = [(Number, Statement)]
public enum InterpreterState: Int, Codable {
case Idle
case ReadingStatement // while parsing code
case Running // while running it
case ReadingInput // while waiting on user input
}
public final class Interpreter: NSObject, NSCoding {
/// Array of program lines
var program: Program = Array()
/// State
var state: InterpreterState = .Idle
etc.
Tuples are not Codable. If you think about it, what should the keys for (Number, Statement) be? (I might have made it sound like named tuples are codable, but they aren't either)
Create your own struct:
struct ProgramLine: Codable {
let lineNumber: Number // assuming these types are codable
let statement: Statement
}
And then your type alias will be codable too (without you doing anything)!
typealias Program = [ProgramLine]

Can I write protocol behave similar to Encodable & Decodable?

The swift4's Codable protocol is extremely useful. It provide default implementation functions if the conformation is rightly defined.
E.g. this is totally fine:
struct Good: Codable {
var foo: String // Non-optional
var bar: Int? // Optional
}
but this one will raise compile error with the request to create protocol conforming
struct Bad: Codable {
var foo: UIButton // Non-optional raise compile error for not conforming Codable Protocol
var bar: UIView? // optional is okay (not compile error because when decode failed, it fallback to nil)
var codable: SomeCodable // if the property is also Codable, then it's fine too!
}
So, the question is: Can I write a protocol that can require its conformance to follow itself (like properties need to conform same protocol)?
If yes, how? If no, why?
Also, I'd also like to know how defining CodingKeys inside the struct can change the encode/decode behaviour? Can I make something like that in my protocol as well?
Martin is correct you cannot make this on your own without touching the compiler.
First let's take a look at this basic example where I explain how coding keys are used.
struct CodableStruct: Codable {
let primitive: Int // No issues yet
enum CodingKeys: String, CodingKey {
case primitive
// This is the default coding key (i.e the JSON has structure ["primitive": 37]
// You can change this key to anything you need
//
// ex case primitive = "any_thing_you_want"
// JSON has to have structure ["any_thing_you_want": 37]
}
}
Changing the codingKey just changes the key the code will use when looking to "decode" that value from your JSON.
Now let's talk about the compiler. Let's say we create another struct
struct NotCodableStruct {
let number: Double
}
This struct does not conform to Codable. If we go and add this into our previous struct we have:
struct CodableStruct: Codable {
let primative: Int
let notCodable: NotCodableStruct // doesn't compile because this doesn't conform to codable
enum CodingKeys: String, CodingKey {
case primative
case notCodable
}
}
Since NotCodableStruct does not conform to Codable the compiler complains. In other words all variables in a struct or object that conforms to Codable must also conform to Codable. See the below screenshot for more information.
Of course if you make NotCodableStruct conform to Codable everyone will be happy again. Since there is no way for you to enforce the requirement that all variables conform to Codable you cannot make a similar protocol.

How to make a struct conforms to a protocol which has a property conforms to another protocol in swift 4?

I was going to reflect some JSON data from web service into swift struct. So I created a protocol which conforms to decodable protocol and planed to create some structs to conform it. This is the protocol I had created:
protocol XFNovelApiResponse: Decodable {
var data: Decodable {get}
var error: NovelApiError {get}
}
struct NovelApiError: Decodable {
let msg: String
let errorCode: String
}
It was compiled. But when I started to write my struct I got an error. The struct's code is here:
struct XFNovelGetNovelsApiResponse: XFNovelApiResponse {
let data: NovelsData
let error: NovelApiError
struct NovelsData: Decodable {
}
}
The error says type 'XFNovelGetNovelsApiResponse' does not conform to protocol 'XFNovelApiResponse'. I know the 'data' property should be implemented in wrong way. How can I fix it? Thanks.
You are asking to describe the kind of type that data can hold, rather than the actual type. That means it needs to be an associatedtype:
protocol XFNovelApiResponse: Decodable {
associatedtype DataType: Decodable
var data: DataType {get}
var error: NovelApiError {get}
}
Note that protocols with associated types can generate a lot of complexity, so you should carefully consider if this protocol is really necessary, or if XFNovelApiResponse could, for example, be generic instead. It depends on what other types implement this protocol.
For example, another implementation of a similar set of data structures without protocols would be:
struct XFNovelApiResponse<DataType: Decodable>: Decodable {
var data: DataType
var error: NovelApiError
}
struct NovelsData: Decodable {
}
struct NovelApiError: Decodable {
let msg: String
let errorCode: String
}
let novels = XFNovelApiResponse(data: NovelsData(),
error: NovelApiError(msg: "", errorCode: ""))
Alternately, you can implement this with classes and subclasses, which allow inheritance. Structs do not inherit from protocols, they conform to protocols. If you really mean inheritance, classes are the right tool. (But I expect generics are the better solution here.)

Nested Codable protocols with Swift 4

I was playing with Swift 4 and Codable a little bit and got stucked with some scenario having nested protocols which all conform to Codable.
Simplified example looks like this:
protocol CodableSomething: Codable {}
protocol CodableAnotherThing: Codable {
var something: CodableSomething { get }
}
struct Model: CodableAnotherThing {
var something: CodableSomething
}
This code is making a build errors with Xcode 9 Beta 5:
Type 'Model' does not conform to protocol 'Decodable'
Type 'Model' does not conform to protocol 'Encodable'
Now, I wasn't expecting these errors as I understood that conformance to these protocols will be auto-generated by the compiler, when in fact, I couldn't even implement this conformance manually without having build errors. I've also tried several different approaches to solve this kind of a nested model structure with using Codable but I just couldn't make it work.
My question: Is this a compiler bug (it's still beta) or I'm doing something wrong?
If you switch protocol
CodableSomething
To a struct you would have no errors,
take it further and read more about Codable
what are the types that a Codable can work on and why ?
up there you are basically saying this to xCode
struct foo: Codable {
var ok: Codable
}
That is not right take a deep look at it,
Codable is a Typealias
you need to conform to to use its subs such as .Decode() , .Encode()
those methods works with values not abstraction types
so giving a Codable Type to a Variable thats not going to work out.
because Codable is a typealias that indicates
Decodable & Encodable
/// A type that can convert itself into and out of an external representation.
public typealias Codable = Decodable & Encodable
and both of Decodable and Encodable are Protocols that make sure those values are encodable and decodable.
so Codable is an abstraction it can't Decode or Encode Variables of it self Type
but can encode and decode Types that are confirmed to it.