Type 'Response' does not conform to protocol 'Decodable' \ 'Encodable' - swift

class ErrorObj: NSObject,Codable {
var numError:Int = 0
var DescriptionError = ""
}
class Response<T: Codable>: NSObject, Codable {
var error:ErrorObj!
var result:T!
func getResponse(errorObj:(ErrorObj)->Void,sucssesObj:(T)->Void) {
if error.numError != 0 {
errorObj(error)
} else{
sucssesObj(result)
}
}
}
errors:
Cannot automatically synthesize 'Decodable' because 'T?' does not conform to 'Decodable'
Protocol requires initializer 'init(from:)' with type 'Decodable'
Cannot automatically synthesize 'Decodable' because 'T?' does not conform to 'Encodable'
Protocol requires initializer 'init(from:)' with type 'Encodable'

The issue is caused by the fact that you declared both properties of Response as implicitly unwrapped optionals (IOU). The compiler cannot autogenerate the required methods of Codable for IOU properties.
However, there's no need to make those IOU anyways. If they are required properties that are always present in the response, make them non-optional. If they might be missing, make them Optional (use ? instead of !).
Also, Swift is not Objective-C. There's no need to make your types inherit from NSObject. And you should also use structs instead of classes unless you explicitly need reference type behaviour. You should also make all properties immutable unless you explicitly need to be able to mutate them.
struct ErrorObj: Codable {
let numError: Int
let description: String
}
struct Response<T: Codable>: Codable {
let error: ErrorObj
let result: T
func getResponse(errorObj: (ErrorObj) -> Void, successObj: (T) -> Void) {
if error.numError != 0 {
errorObj(error)
} else{
successObj(result)
}
}
}

Related

For a generic class, where the generic type conforms to protocol X, how to create an instance of that class with a generic protocol

I want to create a class Game with a generic type which conforms to Equatable. Then I want to be able to use types, which are not by default equatable, like Shape.
If I create an instance with type String, everything works aas intended.
If I create an instance with type Shape, it fails, as expected, since Shape does not conform to Equatable.
My Idea is to use a protocol EquatableShape, which conforms to both Shape and Equatable. Then use it like that:
import SwiftUI
struct Game<Content> where Content: Equatable {
}
var stringGame: Game<String> // ok
var shapeGame: Game<Shape> // obviously fails, since Shapes are not Equatable
// error message: "error: MyPlayground.playground:8:16: error: type 'any Shape' does not conform to protocol 'Equatable'
// Define a protocol EquatableShape, which is Equatable
protocol EquatableShape: Shape & Equatable { }
// Optional: provide a default implementation
extension EquatableShape {
static func == (lhs: any EquatableShape, rhs: any EquatableShape) -> Bool {
return true // some logic here
}
}
// Now every instance which conforms to EquatableShape also conforms to Equatable
struct CircleES: EquatableShape {
func path(in rect: CGRect) -> Path {
return Circle().path(in: rect)
}
}
var circleESGame: Game<CircleES>
// Therefore the compiler should realise this
var equatableShapeGame: Game<EquatableShape> // <= Why does this fail?
// error message: "error: MyPlayground.playground:30:25: error: type 'any EquatableShape' cannot conform to 'Equatable'"
// <= Why does it say EquatableShape CANNOT perform to 'Equatable', while 'any Shape' DOES NOT conform to protocol 'Equatable'
// Workaround 1: Define a container, which stores the shape.
struct EquatableShapeContainer: Equatable {
static func == (lhs: EquatableShapeContainer, rhs: EquatableShapeContainer) -> Bool {
return true
}
let shape: any Shape
}
// This works, but seems like a hacky workaround and not how it should be done.
var equatableShapeContainerGame: Game<EquatableShapeContainer>
EquatableShape is a protocol inheriting Equatable and indeed every type conforming to EquatableShape is also conforming to Equatable.
CircleES on the other hand is a struct (ie. a concrete type) conforming to EquatableShape.
Only concrete types can conform to protocol and that is why
var circleESGame: Game<CircleES>
does compile.
With :
var equatableShapeGame: Game<EquatableShape>
You are passing a protocol inheriting Equatable when the generic constraints asks for a concrete type conforming to Equatable

How to pass any Codable Struct as a return from function and use it in JSONEncoder

As part of network request I want to pass any struct that is Codable into JSONEncoder().encode function. When I pass object directly , lets say
struct MyObject: Codable {}
func createData<T:Codable>(objectToEncode: T) {
JSONEncoder().encode(T)
}
func assigningObject() {
createData(objectToEncode: MyObject())
}
it works perfectly, however I do not know how to pass any codable object that is output of a function, when I call lets say :
func createObject() -> Codable {
return MyObject()
}
func assigningObject() {
let myReturnObject = createObject()
createData(objectToEncode: myReturnObject)
}
I am not able to do createData(objectToEncode: myReturnObject) , because compiler is showing error Value of protocol type 'Codable' (aka 'Decodable & Encodable') cannot conform to 'Decodable'; only struct/enum/class types can conform to protocols
Is there any way how to return struct object from function that will work ?
Solution for iOS 13 and newer is using opaque type :
func createObject() -> some Codable

Can I get the name of a type conforming to a protocol from that protocol?

I would like to know if I can find the name of a type conforming to a given protocol, from that protocol. I was thinking of protocol extension to avoid repetition in every type conforming to that protocol. I tried this:
protocol T {
var type: String { get }
}
extension T {
var type: String {
return String(describing: T.self)
}
}
struct S: T {}
let s = S()
print(s.type)
But this is showing T instead of S.
Is there any way I can do this?
Naturally it's printing T, that's what you asked for with String(describing: T.self). T is always the protocol itself.
Inside the protocol extension Self (capital 'S') is how you refer to the conforming type.
So the extension should be:
extension T {
var typeName: String {
return String(describing: Self.self)
}
}
Aside, the built-in type(of:) function already gives you the dynamic type of any object, so it's not clear that you really need to duplicate this functionality on your own.

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.)

Conform to a protocol misunderstanding

class SuperDelegate <T: AnyObject> {
func addDelegate(delegate: T)
{
}
}
My question is about T key, does it mean the same as id in Objective-c? I mean about case of uses.
how to understand the first line class SuperDelegate <T: AnyObject> Sorry I am new in Swift.
As Objective C program for me this line means that we make class to conform a protocol that has to implement all required method. But I don't understand func addDelegate(delegate: T) is this the same like
- (void)addDelegate:(id)delegate which is a property id <T> delegate.
Yes you are correct in your assumptions that AnyObject behaves like id:
You can call any Objective-C method and access any property on an
AnyObject value without casting to a more specific class type. This
includes Objective-C compatible methods and properties marked with the
#objc attribute.
but you have used it here as a generic type rather than as a concrete type that should be cast to. The class is requiring a type that adheres to the AnyObject protocol but it isn't forcing it to be AnyObject (see header files: cmd + click on AnyObject inside Xcode).
So your instance could be instantiated SuperDelegate<AnyObject> but it could also be instantiated SuperDelegate<NSDate>. This means that the whole subset of ObjC methods and properties cannot be guaranteed as they can with a cast to AnyObject as a concrete type because at runtime T might represent NSDate or NSNumber or any other class.
To achieve what you want you would need to write:
class SuperDelegate {
func addDelegate(delegate: AnyObject)
{
}
}
But Swift is a strongly-typed language and it would normally be the case that you had a delegate protocol and that the delegate for your type adhered to the delegate protocol:
protocol DelegateProtocol {
func somethingHappened()
}
struct MyTypeDelegate:DelegateProtocol {
func somethingHappened() {
print("Thanks for telling me!")
}
}
struct MyType {
var delegate:DelegateProtocol?
func tellDelegateSomethingHappened() {
delegate?.somethingHappened()
}
}
let del = MyTypeDelegate()
var type = MyType()
type.delegate = del
type.tellDelegateSomethingHappened()