I want to use these models both for realm and as codable with Json. How can I do this? As I understand it, Realm doesn't accept it when I use Dictionary.
class QuestionContainer: Codable {
var questionCategories: [Question]
}
class Question: Object, Codable, Identifiable {
#objc dynamic var title: String
#objc dynamic var id: String
#objc dynamic var questions: [QuestionList]
}
class QuestionList: Object, Codable, Identifiable {
#objc dynamic var id: String
#objc dynamic var question: String
#objc dynamic var isQuestionImage, isSectionImage: Bool
#objc dynamic var imageURL: String
#objc dynamic var imageData: Data?
#objc dynamic var sections: [QuestionSections.RawValue : String]
#objc dynamic var selected: String
#objc dynamic var correct: String
}
enum QuestionSections: String, Codable {
case A = "A"
case B = "B"
case C = "C"
case D = "D"
}
Your model should look like:
class QuestionContainer: Object, Codable {
#Persisted var questionCategories: List<Question>
}
class Question: Object, Codable, Identifiable {
#Persisted var title: String
#Persisted var id: String
#Persisted var questions: List<QuestionList
}
class QuestionList: Object, Codable, Identifiable {
#Persisted var id: String
#Persisted var question: String
#Persisted var isQuestionImage: Bool
#Persisted var isSectionImage: Bool
#Persisted var imageURL: String
#Persisted var imageData: Data?
#Persisted var sections: Map<String, String>
#Persisted var selected: String
#Persisted var correct: String
}
Related
i Have a Structure and have some variable in it
struct Home: View {
var token: String
var loginapiurl: String
var companyname: String
#StateObject var dataservice = StatAPI()
i have to pass this token and loginapiurl in the class
class StatAPI: ObservableObject {
#Published var statsdetails = [Result]()
init()
{
print("in init")
let currenDate = getCurrentDate()
let past7DaysBeforeDate = past7dayDate(date1: currenDate)
getStats(dateFrom: past7DaysBeforeDate, dateTo: currenDate)
}
i want to use that two variable in init and passed in to getStats function
I am new to Swiftui. Can anyone help me about this
I've added an Observable Object to my class DetailViewModel, but I am getting an error "Class 'DetailViewModel' has no initializers". Can anyone explain why?
import Foundation
import UIKit
#MainActor
class DetailViewModel: ObservableObject{
#Published var strMeal: String = ""
#Published var strInstructions: String
#Published var strIngredient: String
#Published var strMeasure: String
#Published var strMealThumb:URL?
private func loadMealDetails(idMeal: String) async {
do {
let mealDetailResponse = try await WebServiceRequest().loadData(url: Constants.Urls.getMealByIdUrl(strMeal)) { data in
return try? JSONDecoder().decode(MealDetailModel.self, from:data )
}
} catch {
print(error)
}
}
You have defined some properties (strInstructions, strIngredient, and strMeasure) that don't have initial values specified. Unlike structs, which get synthesized initializers (eg the compiler makes a initializer for us), with a class, we have to create an initializer ourselves (or give all of the properties default values).
With default values, it may look like:
#MainActor
class DetailViewModel: ObservableObject{
#Published var strMeal: String = ""
#Published var strInstructions: String = ""
#Published var strIngredient: String = ""
#Published var strMeasure: String = ""
#Published var strMealThumb:URL?
}
Or, with an initializer, it could be something like:
#MainActor
class DetailViewModel: ObservableObject{
#Published var strMeal: String = ""
#Published var strInstructions: String
#Published var strIngredient: String
#Published var strMeasure: String
#Published var strMealThumb:URL?
init(strInstructions: String, strIngredient: String, strMeasure: String) {
self.strInstructions = strInstructions
self.strIngredient = strIngredient
self.strMeasure = strMeasure
}
}
You may also want to accept values for strMeal and strMealThumb in your initializer -- it's up to you.
I'm try to use my data that fetched from Core Data in nested list, but when I add the "children: .listofTasksArray" the following error is shown:
"Key path value type '[ListOfTasks]?' cannot be converted to contextual type 'FetchedResults?'"
this is the core data file
extension ListOfTasks {
#nonobjc public class func fetchRequest() -> NSFetchRequest<ListOfTasks> {
return NSFetchRequest<ListOfTasks>(entityName: "ListOfTasks")
}
#NSManaged public var addedDate: Date?
#NSManaged public var color: String?
#NSManaged public var favoriteIndex: Int16
#NSManaged public var icon: String?
#NSManaged public var id: UUID?
#NSManaged public var index: Int16
#NSManaged public var isArchived: Bool
#NSManaged public var isFavorite: Bool
#NSManaged public var isLocked: Bool
#NSManaged public var title: String?
#NSManaged public var isList: Bool
#NSManaged public var origin: ListOfTasks?
#NSManaged public var subLists: NSSet?
// The wrapped items
public var wrappedAddedDate: Date {
return addedDate ?? Date()
}
// To convert the color from "String" to "Color" type
public var wrappedColor: Color {
return Color(colorName: color ?? "blue")
}
public var wrappedIcon: String {
return icon ?? "ellipsis.circle.fill"
}
public var wrappedId: UUID {
return id ?? UUID()
}
public var wrappedTitle: String {
return title ?? "Unknown Title"
}
public var listofTasksArray: [ListOfTasks]? {
let set = subLists as? Set<ListOfTasks> ?? nil
return set?.sorted { // sort by index
$0.index > $1.index
}
}
}
and this is the list code that I used to fetch the data and use it in the list trying to make nested list using ListOfTasks property "listofTasksArray" as a child for the list.
struct ListsView: View {
#FetchRequest(entity: ListOfTasks.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \ListOfTasks.index, ascending: true)], animation: .default) private var lists: FetchedResults<ListOfTasks>
var body: some View {
List(lists, children: \.listofTasksArray, rowContent: { Text($0.wrappedTitle) })
}
}
Types of data container are expected to be the same, so try to wrap FetchedResults into an array, like (might be some tuning needed do to optionals)
var body: some View {
List(Array(lists), children: \.listofTasksArray) {
Text($0.wrappedTitle
}
}
Example:
protocol Animal {
#objc dynamic var name: String {get set}
#objc dynamic var age: Int {get set}
}
class Dog: Animal {
#objc dynamic var dogBreed: DogBreed? = nil
}
class Cat: Animal {
#objc dynamic var catBreed: CatBreed? = nil
}
class Bird: Animal {
#objc dynamic var birdBreed: BirdBreed? = nil
}
class Person: Object {
#objc dynamic var name = ""
#objc dynamic var picture: NSData? = nil
let pets = List<Animal>()
}
I'm new in Realm, but I know Realm does not support polymorphism. Is there any option to solve this example?
I've been learning Swift & SwiftUI and all has been going well until very recently. I have successfully used #Published properties to keep my data & views in sync. However, I now want to display some data that is a combination of several #Published properties.
The simplified data model class:
import Foundation
final class GameAPI: ObservableObject {
struct PlayerStats: Identifiable, Codable {
var gamesPlayed: Int
var wins: Int
var losses: Int
}
struct Player: Identifiable, Codable {
var id = UUID()
var name: String
var stats: PlayerStats
}
struct Room: Identifiable, Codable {
var id = UUID()
var name: String
var players: [Player]
}
struct ServerStats {
var totalGamesPlayed: Int
var totalPlayers: Int
var totalPlayersOnline: Int
}
#Published var players: [Player] = []
#Published var rooms: [Room] = []
func addPlayer(name: String) {
players.append(Player(
name: name,
stats: PlayerStats(
gamesPlayed: 0,
wins: 0,
losses: 0
)
))
}
func removePlayer(id: UUID) { ... }
func updatePlayerStats(playerId: UUID, stats: PlayerStats) { ... }
func getLeaderboard() -> [Player] {
return players.sorted({ $0.stats.wins > $1.stats.wins }).prefix(10)
}
func getServerStats() -> ServerStats {
return ServerStats(
totalGamesPlayed: ...,
totalPlayers: ...,
totalPlayersOnline: ...,
)
}
}
View:
import SwiftUI
struct LeaderboardTabView: View {
#EnvironmentObject var gameAPI: GameAPI
var body: some View {
VStack {
Text("TOP PLAYERS")
Leaderboard(model: gameAPI.getLeaderboard())
// ^^^ How can I make the view automatically refresh when players are added/removed or any of the player stats change?
}
}
}
How can I wire up my views to leaderboard & server stats data so that the view refreshes whenever the data model changes?