Post not yet marked as solved
Hello,I'm learning CoreData but my Tutorial is about one year old so not everything is up to date and I don't understand where the problem is. My Project includes an TableViewController with an bar button item. Here is the codeCoreDataResource.swift:import UIKit
import CoreData
class CoreDataResource {
// /Document
var documentDir : URL {
let allUrls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return allUrls[0]
}
let appDelegate = UIApplication.shared.delegate as! AppDelegate
private var managedObjectModel: NSManagedObjectModel {
guard let url = Bundle.main.url(forResource: "Listen", withExtension: "momd") else {
fatalError("fix me: not found?")
}
guard let model = NSManagedObjectModel(contentsOf: url) else {
fatalError("error in the model?")
}
return model
}
private var storeCoordinator: NSPersistentStoreCoordinator {
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.documentDir.appendingPathComponent("Listen.sqlite")
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
} catch {
print(error)
}
return coordinator
}
var managedContext: NSManagedObjectContext {
let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
context.persistentStoreCoordinator = self.storeCoordinator
return context
}
func saveContext() {
if managedContext.hasChanges {
do {
try managedContext.save()
} catch {
print(error)
}
}
}
func loadLists() -> [Liste] {
let request: NSFetchRequest = Liste.fetchRequest()
var listen = [Liste]()
do{
listen = try managedContext.fetch(request)
} catch {
print(error)
}
return listen
}
func newList(_ name: String) {
let newList = NSEntityDescription.insertNewObject(forEntityName: "Liste", into: managedContext) as! Liste
newList.name = name
saveContext()
}
}ListTableViewController.swift:import UIKit
class ListTableViewController: UITableViewController {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var listen = [Liste]()
override func viewDidLoad() {
super.viewDidLoad()
reloadList()
}
private func reloadList() {
listen = appDelegate.coreDataResource.loadLists()
}
@IBAction func addDummyData(_ sender: Any) {
appDelegate.coreDataResource.newList("Test entry")
appDelegate.coreDataResource.saveContext()
reloadList()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath)
let liste = listen[indexPath.row]
cell.textLabel?.text = liste.name
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return listen.count
}
}If I press in Simulator on the addDummyData button the following error occurs:CoreData: error: Mutating a managed object 0x6000026b25c0 <x-coredata:///Liste/t8A4529E8-BD3B-4157-B3AF-E8B011B6C46E2> (0x6000005b6300) after it has been removed from its context.I can't find the mistake. Please help me it's frustrating 😀
Post not yet marked as solved
My listView is simplestruct ListView: View {
var body: some View {
NavigationView {
List(myList) { element in
NavigationLink(destination: NextView()) {
Text(element.name)
}
}
}
}
}Thought I could set a background Image for the whole View with.background(Image("ImageName"))modifier. But the lists background is still white. I don't want to set an image for each row only once for the whole view.Can anyone help?
Post not yet marked as solved
I'm new to SwiftUI and tried my first project on it.So I want to make an iOS app which is showing some data from Firestore in a list. The list is empty because MonsterT is empty. How can I call the init of Class MonsterC?In my SceneDelegate I added following line in func scene and added this variable:class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var monsterT = MonsterC()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionIf using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView().environmentObject(monsterT)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}...My Listimport SwiftUI
struct ContentView: View {
@EnvironmentObject var monsterT: MonsterC
var body: some View {
List(monsterT.monsters, id: \.self) { monster in
Text(monster.name)
}
}
}My MonsterC Class with MonsterObjimport SwiftUI
import FirebaseFirestore
import FirebaseFirestoreSwift
struct MonsterObj: Identifiable, Equatable, Hashable {
var id = UUID()
var name: String
var element: String
var immune: String
var size: String
var twoStarWeakness: String
var threeStarWeakness: String
#if DEBUG
static let exampleMonster = MonsterObj(id: UUID(), name: "Test Monster", element: "Test Element", immun: "Test immune", groesse: "Test size", twoStarWeakness: "Test 2 Weakness", threeStarWeakness: "Test3 Weakness")
#endif
}
class MonsterC: ObservableObject {
var db = Firestore.firestore()
@Published var monsters = [MonsterObj]()
init() {
var monsterCount: [String] = [""]
monsterCount.remove(at: 0)
db.collection("Monster").getDocuments() { (querySnapshot, err) in
if let err = err {
print(err)
} else {
for document in querySnapshot!.documents {
monsterCount.append(document.documentID)
}
}
}
for monsterName in monsterCount {
print(monsterName)
db.collection("Monster").document(monsterName).getDocument { (document, error) in
if let document = document, document.exists {
let elementGetter = document.get("element") as! String
let immuneGetter = document.get("immune") as! String
let sizeGetter = document.get("size") as! String
let twoStarWeaknessGetter = document.get("2 Star Weakness") as! String
let threeStarWeaknessGetter = document.get("3 Star Weakness")as! String
self.monsters.append(MonsterObj.init(name: monsterName, element: elementGetter, immune: immuneGetter, size: sizeGetter, twoStarWeakness: twoStarWeaknessGetter, threeStarWeakness: threeStarWeaknessGetter))
}
}
}
}What am I doing wrong or missing?Thanks in advance 🙂
I'm new to swiftUI.There must be a way to make this better.For example if I add an Item (for example: "name5") to names I have to add a new HStack Block in my Code.How can I do this more efficient?import SwiftUI
struct name: View {
let names = ["name1", "name2", "name3", "name4"]
var body: some View {
List {
VStack {
HStack {
Image(names[0])
Text(names[0])
}
HStack {
Image(names[1])
Text(names[1])
}
HStack {
Image(names[2])
Text(names[2])
}
HStack {
Image(names[3])
Text(names[3])
}
}
}
}
}
struct monsterList_Previews: PreviewProvider {
static var previews: some View {
name()
}
}Maybe something like this.Pseudocode: foreach i in names.count:
HStack {
Image(names[i])
Text(names[i])
}if I add an Item to names it should automatically increase the list by the new element.thanks in advance
Post not yet marked as solved
Hey,I'm a beginner hobby dev who tried cloud storage for first time using SwiftUI.I wanted to make a simple app which only needs to retrieve some values of a Database.I'm using Firebase RealTime Database.My Database structure looks like this:monsterhunter-e8167 Velkhana
HP: 12000element: IceRath
HP: 8000element: FireMy Code looks like this:import SwiftUI
import FirebaseDatabase
struct ContentView: View {
var ref: DatabaseReference = Database.database().reference()
var body: some View {
Button(action: {
self.ref.child("monsterhunter-e8167").child("Velkhana")
.observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let hp = value?["HP"] as? Int ?? 0
print(hp)
// ...
}) { (error) in
print(error.localizedDescription)
}
}) {
Text("print")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}However it is printing out0the expected output should be:12000I figured out "value" is nil but I don't know why."childpath" should be correctCan anyone tell me what I'm doing wrong?
Post not yet marked as solved
I'm still a beginner in Swift and in programming. And I don't have any experience with JSON. Now I tried to make a App on my own. I tried my Code first in Playgrounds but errors occured and I don't know why 😀So first here is my Code:import UIKit
import Foundation
struct MonsterInfo : Decodable {
var id : Int
var name: String
var type: String
var elements: [String]
var ailments: [String]?
var locations: [String]
var resistances: [String]
var weaknesses: [String]
}
func getMonsterInfoAPI(id: Int) {
let url = URL(string: "https://mhw-db.com/monsters/\(id)")!
let session = URLSession.shared
let task = session.dataTask(with: url, completionHandler: {data, response, error in
do {
let json = try? JSONSerialization.jsonObject(with: data!, options: [])
// print(json)
} catch {
print("JSON error: \(error.localizedDescription)")
}
let decoder = JSONDecoder()
let temp = try! decoder.decode(MonsterInfo.self, from: data!)
print(temp.name)
print(temp.locations)
})
task.resume()
}
getMonsterInfoAPI(id: 4)The problem is: If i use print(temp.name) it works but on the other propertys I declared in the Struct it always says "Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "ailments", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected to decode String but found a dictionary instead.", underlyingError: nil)): file MyPlayground.playground, line 34"If I now change the types of the MonsterInfo ailments to dictionary like this...struct MonsterInfo : Decodable {
var id : Int
var name: String
var type: String
var elements: [String]
var ailments: [String:Int]
var locations: [String]
var resistances: [String]
var weaknesses: [String]
}the follwing error occurs:Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.Dictionary<Swift.String, Swift.Int>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "ailments", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Int> but found an array instead.", underlyingError: nil)): file MyPlayground.playground, line 32Why does this error occurs? I'm confused first it says "...but dictionary found" and then "...but found array"How to achieve my aim to get from all "propertys" in my struct the right value even if it is null