Create Fluent Model with String Enum - vapor

Here is my Fluent Model
struct Ailment: PostgreSQLModel {
enum Frequency: String , Content {
case regular = "Regular"
case occasional = "Occasional"
case incidentFound = "Incident Found"
}
var id: Int?
var ailment: String
var frequency: Frequency
var dateIdentified: Date?
var underMedication: Bool
var breifDescription: String
}
I am able to create Fluent Model with Int Enum, but it does not work with String Enum,
I am getting below Exception
Fatal error: Error raised at top level: ⚠️ DecodingError: Cannot initialize Frequency from invalid String value 1
Thanks in advance :)

Referring this Issue it works with Vapor 3.0.6 and Fluent 3.0.0. The table should be created correct if your enum is conform to ReflectionDecodable.

Related

Why does the Sendable type is not checked when defining the generic struct of Sendable types

I'm going through
https://developer.apple.com/videos/play/wwdc2021/10133/
video, and I've created exmple to test Sendable type.
Why does this piece of code nod raise and compiler error?
class Author {
var firstName: String = ""
var secondName: String = ""
var notifCenter: NotificationCenter = NotificationCenter.default
}
struct Pair<T, U> where T: Sendable, U: Sendable {
var first: T
var second: U
}
var k = Pair<Int, Author>(first: 5, second: Author())
I've intentionally added notifCenter stored property to the class of Author not to allow for some compiler magic. Author is clearly not the Sendable type yet the compile doesn't seem to have a problem with it.

iOS Core Data - how to save Tuple property

I'm in process of adding Core Data to my app, started out with a struct like this:
struct Expense: Equatable{
let id: String = UUID().uuidString
var name: String
var description: String
var category: String
var nextBill: Date
var billingCycle: (Int, String)
var currency: Currency?
var price: Decimal
}
Reading documentation look like I'll need to convert it to a class
#objc(Expense)
public class Expense: NSManagedObject {
let id: String = UUID().uuidString
var name: String
var description: String
var category: String
var nextBill: Date
var billingCycle: (Int, String)
var currency: Currency?
var price: Decimal
}
However this appears to have issue with the billingCycle property which is a tuple value ( example of value: 1 per week, 1 per month, 3 per year)
I'm thinking of splitting the billingCycle property into 2 new properties: billingCycleInt and billingCycleString. Would this be the best approach or there is other way?
That would be best. Core Data is— internally— still very much oriented toward Objective-C. As such it has no idea about Swiftisms like tuples. There are other approaches that could work, like trying to get NSCoding to work for this property, but they would all be significantly more complex.
If you’d like to keep the tuple, you might consider adding the two properties you mention and then converting the tuple into a computed property that looks up the values of the other two. Then you can use a Swift tuple where it’s convenient but still work with Core Data.

Model Object Issue

I am trying to create a model object to store json data received from newsAPI. However one of the keys called description matched a reserved keyword in swift. How do I resolve this ? The error message read Error Message: Property 'description' with type 'String?' cannot override a property with type 'String'
class ArticlesData: NSObject {
var author: String?
var title: String?
var description: String?
var publishedAt: String?
var urlImage: String?
var urlWebsite : String?
}
author : Andrew Marino
title : Vergecast: this week’s Section 230 hearing and the season of weird gadgets
description : Nilay, Dieter, and Adi discuss the latest Section 230 congressional hearing featuring the CEOs of Big Tech. Ashley Carman stops by to talk about how gadget makers are turning to shopping channels to market their products.
url : https://www.theverge.com/2020/10/30/21541796/section-230-hearing-gadgets-qvc-razr-2020-review-vergecast-podcast-428
urlToImage : https://cdn.vox-cdn.com/thumbor/sgk9rqbUKhLVhNxKunmuX_Zm6TM=/0x146:2040x1214/fit-in/1200x630/cdn.vox-cdn.com/uploads/chorus_asset/file/19749210/vpavic_200214_3909_samsung_galaxy_Z_flip_0013.jpg
publishedAt : 2020-10-30T14:44:14Z
content : Photo by Vjeran Pavic / The Verge\n\n This week on The Verge’s flagship podcast, The Vergecast: Sen. Ted Cruz (R-TX) yells at Twitter CEO Jack Dorsey, gadget makers are going to QVC, and it is weird ph… [+3098 chars]
Simplest solution: Use a struct, neither a class or even a subclass of NSObject is necessary.
struct ArticlesData {
Otherwise just use a different name.
If you are going to decode the JSON with Decodable add CodingKeys to map the dictionary key to the struct member with a different name.
And don't declare all properties carelessly as optional. Declare only those as optional which can be nil.
I've run into the same 'issue' several times and it's quite annoying indeed. You should rename your property to something else.
How are you mapping your JSON into the object? If you use Codable, you can use custom CodingKeys such as:
class ArticlesData: NSObject, Codable
{
var author: String?
var title: String?
var myDescription: String?
var publishedAt: String?
var urlImage: String?
var urlWebsite: String?
private enum CodingKeys: String, CodingKey
{
case author, title, myDescription = "description", publishedAt, urlImage = "urlToImage", urlWebsite = "url"
}
}
EDIT: As vadian said, you can also use a struct. I actually prefer that solution over renaming the propery to another name than you want.

swift struct JSON id warning

So I am getting a warning (and I can't dismiss it because it won't run the JSON if I do)
The warning is for the following
struct Station: Codable, Identifiable {
let id = UUID() // WARNING: Immutable property will not be decoded because it is declared with an initial value which cannot be overwritten
var name : String
var imageurl : String
var listenlive : String
}
The problem is the following
I can't make it UUID as I get the following error
Type 'Station' does not conform to protocol 'Decodable'
// STATION
struct Sdata: Codable {
var data: [Station]
}
struct Station: Codable, Identifiable {
let id = UUID
var name : String
var imageurl : String
var listenlive : String
}
Also technically the let id is wrong because the JSON has it as _id
"_id":"5f52ed668b964609655b48d1"
So How do I make the warning go away while conforming to the correct value type?
In this case, it's not a matter of "getting rid of the warning". What you are doing seems fundamentally wrong.
The way you declared struct Station, every time a new struct is created, its "id" field is set to a new UUID, that is every struct Station has a different id field, that cannot be changed afterwards.
So if we ignore Codeable for the moment, how would you write such a struct to a file and read it back later, getting the same id? Answer: You can't read it back. At some point you create a struct Station with a new, different UUID, and there is no way to store the one that you wrote to a file. So you have a problem here.
So the problem is quite obvious: If you have a "let" property with a non-constant value, Codeable would have to write it, but Decodable cannot read it, so you have a problem. Make "id" a var, possibly with a constructor that sets it to a new UUID, but it must be changeable.
You need to change it to id:String and use enum CodingKeys for the custom name _id
struct Station: Codable , Identifiable {
var id,name,imageurl,listenlive:String
private enum CodingKeys : String, CodingKey {
case id = "_id", name , imageurl , listenlive
}
}

Swift: get self.description in self.description

I'm trying to modify description output for ErrorProtocol. But this snippet, gives me infinite loop.
enum GeneralError: ErrorProtocol, CustomStringConvertible {
case NoMemory
var description: String {
return String(self).lowercased()
}
}
Changing to self.dynamic type gives me a "generalerror".
Is there any way how to get just "nomemory"? Without using conditionals.
Swift: Convert enum value to String? isn't an exact match for your question, but it really covers the guts of it. In your case, you'll want to change it up a little bit:
enum Error : String, ErrorProtocol, CustomStringConvertible {
case NoMemory
var description : String {
return self.rawValue.lowercaseString
}
}
This works because the default rawValue for enum cases where the associated type is String is the name of the case.
When you call String(self) in GeneralError.description, you're making the String initializer use your object (self) as a CustomStringConvertible to make a new string. Internally, it does this by calling description on it, hence the recursion
What exactly are you trying to achieve?

Resources