I am getting this error Inheritance from non-protocol type 'PFObject' on Xcode with Swift while trying to create a Model, here is the code of the model:
import Foundation
import ParseSwift
import Parse
import SwiftUI
struct Category: ParseObject, PFObject {
// Required properties from ParseObject protocol
var originalData: Data?
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
// Custom fields for the contact's information
var name: String = ""
var cover: String = ""
var color: String = ""
var createdBy: String = ""
}
extension Category {
init(name: String, cover: String, color: String, createdBy: String) {
self.name = name
self.cover = cover
self.color = color
self.createdBy = createdBy
}
}
What am I doing wrong?
It looks like you are trying to use Parse-Swift and the Parse Objective-C SDK at the same time which you shouldn't be doing. Your ParseObject is setup using Parse-Swift so assuming that's what you want to use, remove, import Parse and your Parse Object should look like:
import Foundation
import ParseSwift
import SwiftUI
struct Category: ParseObject {
// Required properties from ParseObject protocol
var originalData: Data?
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
// All Custom fields should be optional
var name: String?
var cover: String?
var color: String?
var createdBy: String?
}
extension Category {
init(name: String, cover: String, color: String, createdBy: String) {
self.name = name
self.cover = cover
self.color = color
self.createdBy = createdBy
}
}
Remove the Parse dependency completely from your project as Parse-Swift doesn't use or need it at all. The playgrounds in Parse-Swift show how to use the SDK correctly along with any imports that are needed to use the SDK.
Related
I have my model called Restaurant:
realm object on kotlin:
class Restaurant : RealmObject {
#PrimaryKey
var _id: ObjectId = ObjectId.create()
var name: String = ""
var adress: String? = null
}
I want to use the _id property. But for that I need to convert to a String in SwiftUI
I tried: restaurant_id as! String, it does not work,
Is is related to this post: https://www.mongodb.com/community/forums/t/swift-convert-objectid-to-string/121829
No real answers there
Any other solutions?
the error when using .toHexString(): Value of type 'any Library_baseObjectId' has no member 'toHexString':
the type of _id in this case:
The error when trying: "\(restaurant._id.stringValue)"
I solved this by adding a getter to the class:
class Restaurant : RealmObject {
#PrimaryKey
var _id: ObjectId = ObjectId.create()
var name: String = ""
var adress: String? = null
fun getID() : String{
return _id.toString()
}
}
ObjectID's in Swift have a stringvalue property which returns the ObjectID as a string
You could do this
let idAsAsString = someRealmObject._id.stringValue
Or for kotlin and other SDK;s
let idAsString = object._id.toString()
In SwiftUI, the id can be accessed in a similar way, and then use the value to init a new string
let x = someRealmObject._id.stringValue
let y = String(stringLiteral: x)
let _ = print(x, y)
Text("\(x) \(y)")
and the output will be
6376886a1dbb3c142318771c 6376886a1dbb3c142318771c
in the console and the same in the Text in the UI
Here's some SwiftUI showing the use
List {
ForEach(myModel) { model in
NavigationLink(destination: SecondView(navigationViewIsActive: $navigationViewIsActive, selectedEntryToShow: model))
{
Text("\(model._id.stringValue)") //ormodel._id.toString()
}
}
}
This Swift model works perfectly and the string of ObjectId can be read per above.
class Restaurant: Object {
#Persisted(primaryKey: true) var _id: ObjectId
#Persisted var name: String = ""
#Persisted var adress: String? = null
}
This question already has answers here:
SwiftUI: data identifier stability and uniqueness
(2 answers)
Closed 1 year ago.
I have a struct which is parsed from JSON, but contains another struct Article that must be identifiable. It looks like this:
import Foundation
struct TopHeadlines: Codable {
var totalArticles: Int
var articles: [Article]
struct Article: Codable {
var title: String
var description: String
var url: String
var image: String
var publishedAt: String
var source: Source
}
struct Source: Codable {
var name: String
var url: String
}
var json: Data? {
return try? JSONEncoder().encode(self)
}
}
extension TopHeadlines.Article: Identifiable {
var id: UUID { return UUID() }
}
I need UUID generated to access image from newImages dictionary:
List(viewModel.articles, id: \.id) { article in
HStack {
OptionalImage(uiImage: viewModel.newsImages[article.id])
Text(article.id.uuidString)
Text(article.id.uuidString)
Text(article.id.uuidString)
}
}
but three text views print three different UUIDs:
CC83B8AE-61B1-4A7D-A8A4-1B1E98C27CE7
545C1D28-F098-48A3-8C3C-A98BB54F9751
39B8383C-A2D8-46B0-BA51-1B861AF09762
How should I create ID for Article struct so it wouldnt be re-generated everytime?
You've declared id as a computed property, so by definition a new UUID instance will be returned every time you access the property.
You need to make the property a stored immutable property to ensure that the UUID never changes.
You also need to manually declare a CodingKey conformant enum and omit the id key from its cases to tell the compiler that id should not be decoded from the JSON.
struct TopHeadlines: Codable {
var totalArticles: Int
var articles: [Article]
struct Article: Codable, Identifiable {
var title: String
var description: String
var url: String
var image: String
var publishedAt: String
var source: Source
let id = UUID()
private enum CodingKeys: String, CodingKey {
case title, description, url, image, publishedAt, source
}
}
struct Source: Codable {
var name: String
var url: String
}
var json: Data? {
return try? JSONEncoder().encode(self)
}
}
The id property in your extension is a computed property, so a new UUID (UUID()) is generated on each call.
Since you can't have stored properties in an extension, try adding it directly to the Article struct, like this:
struct Article: Codable, Identifiable {
var id = UUID()
var title: String
var description: String
var url: String
var image: String
var publishedAt: String
var source: Source
}
This only generates a UUID when the struct is initialized.
extensions cannot store properties, that's why you've implemented id as computed property, and each new UUID() is unique
the most obvious solution is to move it to move it to your struct
struct Article: Codable {
let uuid = UUID()
// ...
}
Declared like this it won't require value both in time of decoding or creating new object.
But if you can't edit this struct(which is probably why you're using an extension), you can do the following: extend your struct with Hashable, then you can access object hashValue which is calculated based on all properties so this value will be the same only for two objects with same values in all properties, which is usually fits good for an unique identifier
extension Article: Hashable {
}
Usage
Text("\(article.hashValue)")
I'm pretty new to xCode so this could have an obvious answer.
I've just learned about environment objects and created the following one:
import SwiftUI
class Data: ObservableObject {
#Published var types = [Type]()
#Published var customers = [Customer]()
#Published var templates = [SubscriptionTemplate]()
#Published var subscriptions = [Subscription]()
#Published var giftCodes = [Giftcode]()
}
As you can see the object contains an array of objects. One of these is a customer array. The customer object looks like this:
import SwiftUI
class Customer: Identifiable, Codable{
var id: Int
var firstname: String
var lastname: String
var address: String
var plz: Int
var place: String
var credit: Int
init(id: Int, firstname: String, lastname: String, address: String, plz: Int, place: String, credit: Int) {
self.id = id
self.firstname = firstname
self.lastname = lastname
self.address = address
self.plz = plz
self.place = place
self.credit = credit
}
}
extension Customer: Equatable {
static func == (lhs: Customer, rhs: Customer) -> Bool {
return lhs.id == rhs.id
}
}
In my project, I implemented an API call to update the customer. This works like a charm, but after updating, I also want to fetch the customer objects with the following method:
API().fetchCustomers { (customers) in
self.data.customers = customers
}
After updating an object this doesn't work. The environment object doesn't update, but after creating a new object or fetching the data initial, it works.
What is the difference between the update and the create / fetch?
Make Customer a value type (ie. struct):
struct Customer: Identifiable, Codable{
var id: Int
// ... other code
i have to quite similar struct objects. but one includes more values than the other. As the initial is required for KituraKuery methods i can not modify it but require more information for future processing.
my problem is now, that these struct objects look like this:
struct provider: Codable {
var firstName: String?
var lastName: String?
var email:String?
}
extension provider: Model{
class Persistence {}
}
struct provider2: Codable {
var firstName: String?
var lastName: String?
var email:String?
var providerCategories: [categories]?
}
extension provider: Model{
class Persistence {}
}
what i need is basically a smarter way to copy information from provider to provider2.
what i did as of now is i provided an init to provider2 taking provider as input and adding all values to it.
struct provider2: Codable {
var firstName: String?
var lastName: String?
var email:String?
var providerCategories: [categories]?
init(provider: provider?) {
if let provider = provider{
firstName = provider.firstName
lastName = provider.lastName
email = provider.lastName
}
}
extension provider: Model{
class Persistence {}
}
i however believe this is probably the worst way and there are much better and more lean approaches to it.
I tried myself on protocols but could that not really get to work.
Any input would be great :)
In your approach both Provider and Provider2 struct are tightly coupled to each other. So lets say in future if you want to change Provider struct or you want to initialise Provider2 struct with another struct, then you need to change lot of things.
We can solve the problem easily by decoupling both Provider and Provider2 struct
protocol BasicInfo {
var firstName: String? { get set }
var lastName: String? { get set }
var email:String? { get set }
}
protocol Address {
var address: String? {get set}
}
struct Provider: BasicInfo {
var firstName: String?
var lastName: String?
var email: String?
}
struct Provider2: BasicInfo, Address {
var firstName: String?
var lastName: String?
var email:String?
var address: String?
init(basic: BasicInfo, add: String) {
firstName = basic.firstName
lastName = basic.lastName
email = basic.email
address = add
}
}
//Below are instances of respective struct
let provider1 = Provider(firstName: "Test1", lastName: "TestLast1", email: "test1#gmail.com")
var provider2 = Provider2(basic: provider1, add: "Germany")
In above code i have two different Struct Provider and Provider2. Provider2 contains more variable than Provider (i have just added a single var to demonstrate). Now lets say in future we don't require Provider to fill Provider2, we have a new struct Provider3 which will fill Provider2 values.
struct Provider3: BasicInfo {
var firstName: String?
var lastName: String?
var email: String?
var middleName: String? //new property added
}
//Below are instances of respective struct
let provider3 = Provider3(firstName: "Test1", lastName: "TestLast1", email: "test1#gmail.com")
var provider2 = Provider2(basic: provider3, add: "Germany")
As you see there is no changes in struct Provider2, we have just introduce a new struct, create instance of new struct and passed that instance to Provider2 init method.
You could use extensions for this:
extension provider {
func asProvider2() -> provider2 {
return provider2(firstName: firstName,
lastName: lastName,
email: email,
providerCategories: nil)
}
}
// Then you can use it like this:
let bar = provider(firstName: "foo", lastName: "bar", email: "baz")
let bar2 = bar.asProvider2()
I would like to return a partial object in a response for another object type.
For example, I have a UserProfile model:
var id: Int?
var email: String
var firstName: String?
var lastName: String?
and an Adult model:
var id: Int?
var nickname: String
var type: String
var user: User.UserProfile
var family: Family
Say I would like to return just the UserProfile's email address in the Adult response, what is the way to go about that?
I have tried an approach with child/parent relationships, where my Adult model is more like:
var id: Int?
var nickname: String
var type: String
var user: User.ID
var family: Family
..but then my response just contains an object ID, but I really want to return a partial (or even full in some cases) object.
Thanks in advance.
The way this is done is to create a 'public' definition of your model, which will represent the JSON you return from your route.
For your model, you might create a struct like this:
struct AdultResponse: Content {
var id: Int?
var nickname: String
var type: String
var email: String
var family: Family
init(adult: Adult) {
self.id = adult.id
self.nickname = adult.nickname
self.type = adult.type
self.email = adult.user.email
self.family = adult.family
}
}
You can then get your Adult model from the database, create an AdultResponse and return that from your route.