ForEach and HStack

Hello
Is there any way to put the 2 Texts in an HStack without putting the 2 ForEachs together?

Code:
Code Block
ForEach(model.data, id: \.objectID){ obj in
Text(model.getValue(obj: obj))
}.onDelete(perform: model.deleteData)
ForEach(date.data, id: \.objectID){ obj1 in
Text("\(date.getValue(obj: obj1), formatter: dateFormatter)")
}.onDelete(perform: date.deleteData)

Thank you
Answered by OOPer in 665329022

What do you mean with combined entity and how do I do it?

Define only one Entity CombinedContent with two Attributes in your xcdatamodel:
  • value of type String

  • date of type Date

You just need only one DataModel class:
Code Block
class DataModel: ObservableObject{
@Published var data: [CombinedContent] = []
var txt = ""
var dataAttuale = Date()
let context = persistentContainer.viewContext
init() {
readData()
}
func readData(){
let request: NSFetchRequest<CombinedContent> = CombinedContent.fetchRequest()
do {
let results = try context.fetch(request)
self.data = results
} catch {
print(error.localizedDescription)
}
}
func writeData(){
let entity = NSEntityDescription.insertNewObject(forEntityName: "CombinedContent", into: context) as! CombinedContent
entity.value = txt
entity.date = dataAttuale
do {
try context.save()
self.data.append(entity)
} catch {
print(error.localizedDescription)
}
}
func deleteData(indexSet: IndexSet){
for index in indexSet{
do {
let obj = data[index]
context.delete(obj)
try context.save()
let index = data.firstIndex(of: obj)
data.remove(at: index!)
} catch {
print(error.localizedDescription)
}
}
}
func updateData(){
}
}


You can use it as:
Code Block
ForEach(combinedModel.data, id: \.objectID){ obj in
HStack {
Text(obj.value)
Text("\(obj.date, formatter: dateFormatter)")
}
}.onDelete(perform: combinedModel.deleteData)


Can you show enough code and clarify what you want to do?

What are model.data and date.data? Are they Arrays of the same length? Or something else?
If you combine model and date in a single struct (if that make sense, which supposes that the 2 sets are coordinated), then you can have a single forEach.
Code Block
@ObservedObject var model = dataModel()
@ObservedObject var date = dataModel1()

dataModel and dataModel1 are two different classes which contain two different arrays.

The two classes have to be sperate.

The arrays have the same length because :
Code Block
Button(action: {
model.writeData()
date.writeData()
}) {
Image(systemName: "plus")
}

model.writeData() saves the String that is in the TextFiled and date.writeData()saves the Date.

The two classes have to be sperate.

Can you explain why?
Code Block
var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "CoreDataModel")
container.loadPersistentStores(completionHandler: {(StoreDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext() {
let context = persistentContainer.viewContext
if context.hasChanges{
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
class dataModel: ObservableObject{
@Published var data: [NSManagedObject] = [] //Contiene i dati, tutti i favorites
@Published var txt = ""
let context = persistentContainer.viewContext
init() {
readData()
}
func readData(){
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Content")
do {
let results = try context.fetch(request)
self.data = results as! [NSManagedObject]
} catch {
print(error.localizedDescription)
}
}
func writeData(){
let entity = NSEntityDescription.insertNewObject(forEntityName: "Content", into: context)
entity.setValue(txt, forKey: "value")
do {
try context.save()
self.data.append(entity)
//txt = ""
} catch {
print(error.localizedDescription)
}
}
func deleteData(indexSet: IndexSet){
for index in indexSet{
do {
let obj = data[index]
context.delete(obj)
try context.save()
let index = data.firstIndex(of: obj)
data.remove(at: index!)
} catch {
print(error.localizedDescription)
}
}
}
func updateData(){
}
func getValue(obj: NSManagedObject) -> String{
return obj.value(forKey: "value") as! String
}
}
class dataModel1: ObservableObject{
@Published var data: [NSManagedObject] = [] //Contiene i dati, tutti i favorites
@Published var dataAttuale = Date()
let context = persistentContainer.viewContext
init() {
readData()
}
func readData(){
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Content2")
do {
let results = try context.fetch(request)
self.data = results as! [NSManagedObject]
} catch {
print(error.localizedDescription)
}
}
func writeData(){
let entity = NSEntityDescription.insertNewObject(forEntityName: "Content2", into: context)
entity.setValue(dataAttuale, forKey: "date")
do {
try context.save()
self.data.append(entity)
//txt = ""
} catch {
print(error.localizedDescription)
}
}
func deleteData(indexSet: IndexSet){
for index in indexSet{
do {
let obj = data[index]
context.delete(obj)
try context.save()
let index = data.firstIndex(of: obj)
data.remove(at: index!)
} catch {
print(error.localizedDescription)
}
}
}
func updateData(){
}
func getValue(obj: NSManagedObject) -> Date{
return obj.value(forKey: "date") as! Date
}
}

The getValue function returns two different types in the two classes, thats why I need two FoeEach loops

The getValue function returns two different types in the two classes,

Thanks for showing your code. And your code revealed that if you define a combined entity, your code all things would be solved.

And your code revealed that if you define a combined entity, your code all things would be solved.

What do you mean with combined entity and how do I do it?



Accepted Answer

What do you mean with combined entity and how do I do it?

Define only one Entity CombinedContent with two Attributes in your xcdatamodel:
  • value of type String

  • date of type Date

You just need only one DataModel class:
Code Block
class DataModel: ObservableObject{
@Published var data: [CombinedContent] = []
var txt = ""
var dataAttuale = Date()
let context = persistentContainer.viewContext
init() {
readData()
}
func readData(){
let request: NSFetchRequest<CombinedContent> = CombinedContent.fetchRequest()
do {
let results = try context.fetch(request)
self.data = results
} catch {
print(error.localizedDescription)
}
}
func writeData(){
let entity = NSEntityDescription.insertNewObject(forEntityName: "CombinedContent", into: context) as! CombinedContent
entity.value = txt
entity.date = dataAttuale
do {
try context.save()
self.data.append(entity)
} catch {
print(error.localizedDescription)
}
}
func deleteData(indexSet: IndexSet){
for index in indexSet{
do {
let obj = data[index]
context.delete(obj)
try context.save()
let index = data.firstIndex(of: obj)
data.remove(at: index!)
} catch {
print(error.localizedDescription)
}
}
}
func updateData(){
}
}


You can use it as:
Code Block
ForEach(combinedModel.data, id: \.objectID){ obj in
HStack {
Text(obj.value)
Text("\(obj.date, formatter: dateFormatter)")
}
}.onDelete(perform: combinedModel.deleteData)


ForEach and HStack
 
 
Q