Post

Replies

Boosts

Views

Activity

PDFKit - Wrapping text
Dear all, I have an app in which I'm trying to create a pdf from the data stored. Everything is working fine except the fact that the text is not following the page margins, going out of the page of being truncated without being written on the line below. Has anybody experienced the same in the past? Please assist, I'm getting out of my mind with this in the last two days... Here the code of the function which is creating the PDF. let pdfMetaData = [ kCGPDFContextCreator: "Your App Name", kCGPDFContextAuthor: "Your Name", kCGPDFContextTitle: "Allenamento" ] let pageWidth = 8.5 * 72.0 // Standard letter size in points (8.5 x 11 inches) let pageHeight = 11 * 72.0 let pageSize = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight) let margin: CGFloat = 20.0 let pdfData = NSMutableData() guard let consumer = CGDataConsumer(data: pdfData as CFMutableData) else { print("Errore nella creazione del consumer") return } var mediaBox = pageSize guard let pdfContext = CGContext(consumer: consumer, mediaBox: &mediaBox, pdfMetaData as CFDictionary) else { print("Errore nella creazione del contesto PDF") return } pdfContext.beginPDFPage(nil) // Parte superiore della pagina ... // Disegno del rettangolo "MATERIALE DA ALLENAMENTO" ... // Disegno del rettangolo "ESERCITAZIONI ALLENAMENTO" let exercisesRect = CGRect(x: margin, y: cellYPosition - 45, width: pageWidth - 2 * margin, height: 25) pdfContext.setFillColor(NSColor.lightGray.cgColor) pdfContext.fill(exercisesRect) pdfContext.setStrokeColor(NSColor.black.cgColor) pdfContext.stroke(exercisesRect) let exercisesText = "ESERCITAZIONI ALLENAMENTO" let exercisesAttributedString = NSAttributedString(string: exercisesText, attributes: boldAttributes) let exercisesTextPosition = CGPoint(x: exercisesRect.midX - exercisesAttributedString.size().width / 2, y: exercisesRect.midY - 5) drawText(attributedString: exercisesAttributedString, position: exercisesTextPosition, context: pdfContext) // Iniziamo a disegnare le informazioni degli esercizi let sortedExercises = training.trainingExercises.sorted { $0.order < $1.order } var currentY = exercisesRect.minY - 30 for trainingExercise in sortedExercises { // Gestione del wrap text e posizionamento su più pagine let remainingHeight = currentY - margin if remainingHeight < 100 { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } // Disegna la durata let durationText = "\(trainingExercise.duration) min" let durationAttributedString = NSAttributedString(string: durationText, attributes: boldAttributes) drawText(attributedString: durationAttributedString, position: CGPoint(x: margin, y: currentY), context: pdfContext) currentY -= 20 // Disegna la descrizione con wrap text let descriptionText = trainingExercise.exercise.exerciseDescription let descriptionAttributedString = NSAttributedString(string: descriptionText, attributes: regularAttributes) let maxTextWidth = pageWidth - 2 * margin let descriptionBoundingBox = descriptionAttributedString.boundingRect(with: CGSize(width: maxTextWidth, height: .greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading]) if currentY - descriptionBoundingBox.height < margin { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } // Disegno della descrizione con supporto per il wrap text let descriptionFramesetter = CTFramesetterCreateWithAttributedString(descriptionAttributedString) let descriptionPath = CGPath(rect: CGRect(x: margin, y: currentY - descriptionBoundingBox.height, width: maxTextWidth, height: descriptionBoundingBox.height), transform: nil) let descriptionFrame = CTFramesetterCreateFrame(descriptionFramesetter, CFRangeMake(0, 0), descriptionPath, nil) CTFrameDraw(descriptionFrame, pdfContext) currentY -= descriptionBoundingBox.height + 10 // Disegna l'immagine sotto la descrizione if let imagePath = trainingExercise.exercise.imagePath, let image = NSImage(contentsOfFile: imagePath) { let imageCG = image.cgImage(forProposedRect: nil, context: nil, hints: nil) let imageAspect = CGFloat(imageCG!.width) / CGFloat(imageCG!.height) let targetWidth = min(maxTextWidth, CGFloat(400)) let targetHeight = targetWidth / imageAspect if currentY - targetHeight < margin { pdfContext.endPDFPage() pdfContext.beginPDFPage(nil) currentY = pageHeight - margin } let imageTargetRect = CGRect(x: margin, y: currentY - targetHeight, width: targetWidth, height: targetHeight) pdfContext.draw(imageCG!, in: imageTargetRect) currentY -= targetHeight + 10 } // Disegna una linea sottile come separatore pdfContext.setStrokeColor(NSColor.lightGray.cgColor) pdfContext.setLineWidth(1.0) let lineYPosition = currentY - 5 pdfContext.move(to: CGPoint(x: margin, y: lineYPosition)) pdfContext.addLine(to: CGPoint(x: pageWidth - margin, y: lineYPosition)) pdfContext.strokePath() currentY -= 20 // Spazio tra esercizi } pdfContext.endPDFPage() pdfContext.closePDF() let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let fileName = "Allenamento_\(dateFormatter.string(from: training.date)).pdf" if let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { let fileURL = documentsURL.appendingPathComponent(fileName) do { ... } } catch { print("Errore durante il salvataggio del PDF: \(error)") } } } private func drawText(attributedString: NSAttributedString, position: CGPoint, context: CGContext) { let line = CTLineCreateWithAttributedString(attributedString) context.textPosition = position CTLineDraw(line, context) }
0
1
254
Aug ’24
MacOs sheet not opening and application stuck
Dear all, I'm developing an application with SwiftData for Mac and since the beginning I'm experiencing issues in opening sheets. In particular, I have a view where I'm trying to open a sheet which is called TrainingAttendanceView, but it not working at all. When I click on it, the application is stuck and not working anymore. Debugger is not retrieving anything and I don't have any clue on what to do. Could you please let me know what I'm doing wrong or if there is any possible workaround? Thanks in advance for the support, A. Here the code of the view where I'm calling the sheet: import SwiftUI import SwiftData struct CalendarView: View { @Environment(\.modelContext) private var context @ObservedObject var season: Season @Query var trainings: [Training] @State private var isAddingTraining = false @State private var trainingToEdit: Training? @State private var trainingToDelete: Training? @State private var trainingForAttendance: Training? @State private var showAlert = false @State private var isShowingAttendance = false var body: some View { VStack { ScrollView { VStack(alignment: .leading, spacing: 12) { ForEach(months, id: \.self) { month in monthView(for: month) } } .padding() } .alert(isPresented: $showAlert) { Alert( title: Text("Conferma cancellazione"), message: Text("Sei sicuro di voler cancellare questo allenamento?"), primaryButton: .destructive(Text("Elimina")) { if let training = trainingToDelete { deleteTraining(training) } }, secondaryButton: .cancel { trainingToDelete = nil } ) } .sheet(isPresented: $isAddingTraining) { if let trainingToEdit = trainingToEdit { EditTrainingView(isEditingTraining: $isAddingTraining, season: season, training: trainingToEdit) } else { AddTrainingView(isAddingTraining: $isAddingTraining, season: season) } } .sheet(isPresented: $isShowingAttendance) { if let training = trainingForAttendance { TrainingAttendanceView(season: season, trainingDate: training.date, training: training) } } .toolbar { ToolbarItem(placement: .confirmationAction) { Button(action: { isAddingTraining = true trainingToEdit = nil }) { Text("+ Add Training") .foregroundColor(.blue) } } } } } private var trainingsByMonth: [String: [Training]] { ... } private var months: [String] { ... } private func monthIndex(for monthString: String) -> String? { ... } private func deleteTraining(_ training: Training) { ... } private func monthView(for month: String) -> some View { VStack(alignment: .leading, spacing: 8) { Text(month) .font(.headline) .padding(8) .background(Color.clear) if let monthIndex = monthIndex(for: month), let trainingsInMonth = trainingsByMonth[monthIndex] { if trainingsInMonth.isEmpty { Text("Non ci sono eventi per questo mese") .padding(8) } else { ForEach(trainingsInMonth, id: \.self) { training in HStack(alignment: .center, spacing: 8) { Rectangle() .fill(Color.green) .frame(width: 4) VStack(alignment: .leading, spacing: 4) { Text("Allenamento") .font(.subheadline) .bold() Text(training.date, style: .date) .font(.footnote) Text("Ore: \(training.startTime, style: .time) - \(training.endTime, style: .time)") .font(.footnote) } Spacer() HStack(spacing: 12) { Button(action: { trainingToEdit = training isAddingTraining = true }) { Image(systemName: "pencil") } .buttonStyle(BorderlessButtonStyle()) .foregroundColor(.blue) Button(action: { trainingForAttendance = training isShowingAttendance = true }) { Image(systemName: "person.3.fill") } .buttonStyle(BorderlessButtonStyle()) .foregroundColor(.blue) Button(action: { trainingToDelete = training showAlert = true }) { Image(systemName: "trash") .foregroundColor(.red) } .buttonStyle(BorderlessButtonStyle()) } .frame(width: 100, alignment: .center) } } } } else { Text("Non ci sono eventi per questo mese") .padding(8) } } .padding() } } While here the starting code of the TrainingAttendanceView: import SwiftData struct TrainingAttendanceView: View { @Environment(\.modelContext) private var context @ObservedObject var season: Season var trainingDate: Date @ObservedObject var training: Training @State private var attendance: [PlayerAttendance] = [] @Query private var players: [Player] init(season: Season, trainingDate: Date, training: Training) { self.season = season self.trainingDate = trainingDate self.training = training ...
1
0
328
Aug ’24
Swiftdata with Date
Dear all, I'm going out of mind with the following issue. I have a view where I'm selecting a date through a datepicker. Then I'm inserting some other data and then I'm trying to save, see private func saveTraining(). But the date which is used to save the training is always one day before the selected date and more than this, I'm not able to save it without time. As I have then a calendar where the saved trainings need to be displayed, I'm not able to match it. Did anybody already face this issue? How can I solve it? I'm reporting here the code of the view where you can also find the checks I put to verify values/ dates: import SwiftData import AppKit struct AddTrainingView: View { @Environment(\.modelContext) private var context @Binding var isAddingTraining: Bool @ObservedObject var season: Season @Binding var selectedDate: Date @State private var trainingStartTime = Date() @State private var trainingEndTime = Date() @State private var trainingConditionalGoal = "" @State private var trainingTacticalGoal = "" @State private var trainingExercises: [TrainingExercise] = [] @State private var showExercisePicker = false @State private var currentTraining: Training? init(isAddingTraining: Binding<Bool>, selectedDate: Binding<Date>, season: Season, currentTraining: Training? = nil) { self._isAddingTraining = isAddingTraining self._selectedDate = selectedDate self.season = season self._currentTraining = State(initialValue: currentTraining) if let training = currentTraining { self._trainingStartTime = State(initialValue: training.startTime) self._trainingEndTime = State(initialValue: training.endTime) self._trainingConditionalGoal = State(initialValue: training.conditionalGoal) self._trainingTacticalGoal = State(initialValue: training.tacticalGoal) self._trainingExercises = State(initialValue: training.trainingExercises) } } var body: some View { VStack(alignment: .leading, spacing: 16) { Text("Aggiungi Allenamento") .font(.title) .bold() .padding(.top) VStack(alignment: .leading) { Text("Data allenamento:") DatePicker("", selection: $selectedDate, displayedComponents: .date) .datePickerStyle(.field) } .padding(.bottom, 10) ... Button("Salva") { saveTraining() isAddingTraining = false dismiss() } .buttonStyle(.borderedProminent) .tint(.blue) Button("Visualizza PDF") { createPDF() } .buttonStyle(.borderedProminent) .tint(.blue) Spacer() } .padding(.bottom) } .padding() .frame(maxWidth: .infinity, maxHeight: .infinity) } private func saveTraining() { // Creiamo un'istanza del calendario corrente var calendar = Calendar.current calendar.timeZone = TimeZone.current // Assicuriamoci di utilizzare il fuso orario locale // Estrarre solo i componenti di data dalla data selezionata let components = calendar.dateComponents([.year, .month, .day], from: selectedDate) // Creiamo una nuova data con i soli componenti di anno, mese e giorno guard let truncatedDate = calendar.date(from: components) else { print("Errore nella creazione della data troncata") return } // Stampa di debug per verificare la data selezionata e quella troncata print("Data selezionata per l'allenamento: \(selectedDate)") print("Data troncata che verrà salvata: \(truncatedDate)") let newTraining = Training( date: truncatedDate, startTime: trainingStartTime, endTime: trainingEndTime, conditionalGoal: trainingConditionalGoal, tacticalGoal: trainingTacticalGoal, season: season ) // Verifica che la data sia correttamente impostata print("Data che verrà salvata: \(newTraining.date)") newTraining.trainingExercises = trainingExercises context.insert(newTraining) do { try context.save() print("Allenamento salvato correttamente.") } catch { print("Errore nel salvataggio: \(error.localizedDescription)") } } private var dateFormatter: DateFormatter { let formatter = DateFormatter() formatter.dateStyle = .short return formatter } private var timeFormatter: DateFormatter { let formatter = DateFormatter() formatter.timeStyle = .short return formatter } } } Example: when I'm selecting 2023-08-21, the debugger retrieves me following data: Data selezionata per l'allenamento: 2023-08-20 22:00:00 +0000 Data troncata che verrà salvata: 2023-08-20 22:00:00 +0000 Data che verrà salvata: 2023-08-20 22:00:00 +0000 Allenamento salvato correttamente.
3
0
658
Aug ’24
App icon
Dear all, I'm building my first MacOs app. I've created my app icon and add it to AppIcon folder, but when I'm building the application the icon shows in the dock of the screen with no rounded borders like all the other apps. I'm attaching here the icon and as you can see it has sharp edges. It is the same way in which it shows on the dock. Why? Has anybody experienced the same? Thanks for the support in advance, A.
1
0
577
Aug ’24
Query with Predicate
Dear all, I have the following two classes: Stagioni: import SwiftData @Model class Stagione { @Attribute(.unique) var idStagione: String var categoriaStagione: String var miaSquadra: String @Relationship(deleteRule: .cascade) var rosa: [Rosa]? @Relationship(deleteRule: .cascade) var squadra: [Squadre]? @Relationship(deleteRule: .cascade) var partita: [CalendarioPartite]? init(idStagione: String, categoriaStagione: String, miaSquadra: String) { self.idStagione = idStagione self.categoriaStagione = categoriaStagione self.miaSquadra = miaSquadra } } CalendarioPartite: import SwiftData @Model class CalendarioPartite { var idGiornata: Int var dataPartita: Date var squadraCasa: String var squadraTrasferta: String var golCasa: Int var golTrasferta: Int var stagione: Stagione? init(idGiornata: Int, dataPartita: Date, squadraCasa: String, squadraTrasferta: String, golCasa: Int, golTrasferta: Int) { self.idGiornata = idGiornata self.dataPartita = dataPartita self.squadraCasa = squadraCasa self.squadraTrasferta = squadraTrasferta self.golCasa = golCasa self.golTrasferta = golTrasferta } } Now, I'd like to have a query which is showing in a view the list of partite depending on a selection of a specific Stagione. I've tried with the following query, but I'm getting the following error: "Instance member 'selectedStagione' cannot be used on type 'CalendarioCampionatoView'; did you mean to use a value of this type instead?" @Query(filter: #Predicate<CalendarioPartite> { $0.stagione == selectedStagione}) private var partite: [CalendarioPartite] = [] What I'm doing wrong? Thanks, A.
2
0
431
May ’24
Autocomplete with SwiftData
Dear all, I'm building an app leveraging SwiftData and I have the following two classes: Stagione: import SwiftData @Model class Stagione { @Attribute(.unique) var idStagione: String var categoriaStagione: String var miaSquadra: String @Relationship(deleteRule: .cascade) var rosa: [Rosa]? @Relationship(deleteRule: .cascade) var squadra: [Squadre]? @Relationship(deleteRule: .cascade) var partita: [CalendarioPartite]? init(idStagione: String, categoriaStagione: String, miaSquadra: String) { self.idStagione = idStagione self.categoriaStagione = categoriaStagione self.miaSquadra = miaSquadra } } Squadre: import SwiftData @Model class Squadre { var squadraCampionato: String var stagione: Stagione? init(squadraCampionato: String) { self.squadraCampionato = squadraCampionato } } Now, I have a view in which I'm calling a sheet to insert some Squadre: // Presenta il foglio per aggiungere una nuova partita GroupBox(label: Text("Dettagli Partita").font(.headline).padding()) { VStack { HStack { Text("Giornata:") TextField("Giornata", text: $idGiornata) .frame(width: 30) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } DatePicker("Data Partita:", selection: $dataPartita, displayedComponents: .date) .padding() HStack { Text("Squadra Casa:") .frame(width: 150) TextField("Squadra Casa", text: $squadraCasa) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() TextField("Gol Casa", text: $golCasa) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } HStack { Text("Squadra Trasferta:") .frame(width: 150) TextField("Squadra Trasferta", text: $squadraTrasferta) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() TextField("Gol Trasferta", text: $golTrasferta) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } HStack { Button("Salva") { if let partitaSelezionata = partitaSelezionata { // Se è stata selezionata una partita, aggiorna i suoi dati if let index = partite.firstIndex(where: { $0.id == partitaSelezionata.id }) { partite[index].idGiornata = Int(idGiornata) ?? 0 partite[index].dataPartita = dataPartita partite[index].squadraCasa = squadraCasa partite[index].golCasa = Int(golCasa) ?? 0 partite[index].squadraTrasferta = squadraTrasferta partite[index].golTrasferta = Int(golTrasferta) ?? 0 } } else { // Altrimenti, aggiungi una nuova partita aggiungiPartita(stagione: stagione) } // Chiudi il foglio di presentazione mostraAggiungiPartita = false // Resetta il campo di input idGiornata = "" dataPartita = Date() squadraCasa = "" golCasa = "" squadraTrasferta = "" golTrasferta = "" } .buttonStyle(.borderedProminent) .disabled(idGiornata.isEmpty || squadraCasa.isEmpty || squadraTrasferta.isEmpty || golCasa.isEmpty || golTrasferta.isEmpty) // Bottone Chiudi Button("Chiudi") { mostraAggiungiPartita = false } .buttonStyle(.borderedProminent) } } .padding() } } I'd like to insert a autocomplete function in the textfields "Squadra Casa" and "Squadra Trasferta", based on the list of Squadre contained in the class "Squadre" and filtered for a specific Stagione. Has anybody of you made something similar? Do you have any suggestions or code example which I can use? Thanks, A.
2
0
437
May ’24
Edit Swiftdata data
Dear all, I'm quite new to SwiftUI. I have a view where I'd like to open a sheet to edit data in a List. Here below the code of the view: import SwiftUI import SwiftData struct SettingsView: View { @Query(sort: \Stagione.idStagione) private var usoStagione: [Stagione] @Environment(\.modelContext) private var context @State private var stagione = String(Calendar.current.component(.year, from: Date())) @State private var miaSquadra = "" @State private var categoria = "" @State private var selStagione = Set<Stagione>() @State private var modificaStagione = false var body: some View { NavigationStack { GroupBox("Stagione") { Form { TextField("Stagione:", text: $stagione) .frame(width: 150) TextField("Categoria:", text: $categoria) .frame(width: 400) TextField("Mia squadra:", text: $miaSquadra) .frame(width: 400) Button("Salva") { let nuovaStagione = Stagione(idStagione: stagione, categoriaStagione: categoria, miaSquadra: miaSquadra) context.insert(nuovaStagione) miaSquadra = "" categoria = "" stagione = String(Calendar.current.component(.year, from: Date())) } .frame(maxWidth: .infinity, alignment: .trailing) .buttonStyle(.borderedProminent) .disabled(categoria.isEmpty || miaSquadra.isEmpty) } List(selection: $selStagione) { ForEach(usoStagione, id: \.self) { stag in VStack(alignment: .leading) { Text("\(stag.idStagione)").font(.title2) Text("\(stag.miaSquadra)").foregroundStyle(.secondary) Text("\(stag.categoriaStagione)").foregroundStyle(.secondary) } } .contextMenu() { Button(action: { selStagione.forEach(context.delete) }) { Text("Cancella") } Button(action: { self.modificaStagione = true }) { Text("Modifica") } } } .sheet(isPresented: $modificaStagione) { ModificaStagione(stagione: Stagione) } .listStyle(.plain) .textFieldStyle(.roundedBorder) .padding() } } .padding() .textFieldStyle(.roundedBorder) .navigationTitle("Impostazioni") GroupBox("Squadre") { } } } #Preview { SettingsView() .environmentObject(NavigationStateManager()) .modelContainer(for: Stagione.self, inMemory: true) } While here below the code of the view ModificaStagione: import SwiftUI struct ModificaStagione: View { @Environment(\.dismiss) private var dismiss let stagione: Stagione @State private var idStagione = "" @State private var categoria = "" @State private var miaSquadra = "" @State private var vistaPrecedente = true var body: some View { VStack (alignment: .leading) { GroupBox { LabeledContent { TextField("", text: $categoria) .frame(width: 400) } label: { Text("Categoria:") } LabeledContent { TextField("", text: $miaSquadra) .frame(width: 400) } label: { Text("Mia squadra:") } if modifica { Button("Aggiorna dati") { stagione.idStagione = idStagione stagione.categoriaStagione = categoria stagione.miaSquadra = miaSquadra dismiss() } .buttonStyle(.borderedProminent) } } .padding() .textFieldStyle(.roundedBorder) .navigationTitle("Modifica dati stagione") } .onAppear { idStagione = stagione.idStagione categoria = stagione.categoriaStagione miaSquadra = stagione.miaSquadra } } var modifica: Bool { categoria != stagione.categoriaStagione || miaSquadra != stagione.miaSquadra } } In the "Setting" view I receive an error message when I call the view "Modifica Stagione "saying that "Cannot convert value of type 'Stagione.Type' to expected argument type 'Stagione'". What am I doing wrong? Thanks in advance, A.
1
0
595
Apr ’24
Disable button not working
Dear all, I have a view with the following code. When I'm inserting data into the two textfields the button remains disabled. struct SettingsView: View { @Environment(\.modelContext) private var context @State private var stagione = Calendar.current.component(.year, from: Date()) @State private var miaSquadra = "" @State private var categoria = "" var body: some View { NavigationStack { GroupBox("Stagione") { Form { TextField("Stagione:", value: $stagione, formatter: NumberFormatter()) .frame(width: 150) TextField("Categoria:", text: $categoria) .frame(width: 400) TextField("Mia squadra:", value: $miaSquadra, formatter: NumberFormatter()) .frame(width: 400) Button("Salva") { let nuovaStagione = Stagione(idStagione: stagione, categoriaStagione: categoria, miaSquadra: miaSquadra) context.insert(nuovaStagione) } .frame(maxWidth: .infinity, alignment: .trailing) .buttonStyle(.borderedProminent) .disabled(categoria.isEmpty || miaSquadra.isEmpty) } } .padding() GroupBox("Squadre") { } } .navigationTitle("Impostazioni") } } #Preview { SettingsView() .environmentObject(NavigationStateManager()) } What am I doing wrong? Thanks, A.
1
0
414
Apr ’24
App design and set up
Dear all, please be patient with me as I'm quite new to SwiftUI. I'm designing and setting up my first SwiftUI app. I'd like to release it for Mac and iPad. I'm leveraging the NavigationSplit View, storing all the data in SwiftData. The whole application and dataset is driven by the selection of a value at the beginning. In fact I have a table like the one below (and all the other tables have a relationship one to many with this one): import SwiftData @Model class Stagione { var initStagione: Bool var idStagione: idStagione init(initStagione: Bool, idStagione: idStagione) { self.initStagione = initStagione self.idStagione = idStagione } } enum idStagione: Int, Codable, Identifiable, CaseIterable { case PrimoAnno, SecondoAnno, TerzoAnno, QuartoAnno, QuintoAnno, SestoAnno, SettimoAnno var id: Self { self } var descr: String { switch self { case .PrimoAnno: "2023/2024" case .SecondoAnno: "2024/2025" case .TerzoAnno: "2025/2026" case .QuartoAnno: "2026/2027" case .QuintoAnno: "2027/2028" case .SestoAnno: "2028/2029" case .SettimoAnno: "2029/2030" } } } I'd like to understand, based on your suggestion, how I can place the selection of the idStagione when the app is launched so that all the data displayed in the application are filtered by that parameter. On the other hand, if the parameter is changed I'd like the application to change the data shown. I was thinking of two possible options: Having a form with a picker to select the idStagione Place the picker in the sidebar Do you have any suggestion? Is there any example of something with the same logic that you can share with me? Thanks in advance for your support, A.
4
0
459
Apr ’24
Football League calendar display view
Dear all, I'm quite new to SwiftUI and I'm trying to build my first app. I have a data model file like the one below (I'm just posting a portion of it): import Foundation struct CalendarioPartite: Identifiable, Hashable, Equatable { let id = UUID() let stagione: String let giornata: Int let datapartita: String let squadracasa: String let golsquadracasa: Int let squadratrasferta: String let golsquadratrasferta: Int init(stagione: String, giornata: Int, datapartita: String, squadracasa: String, golsquadracasa: Int, squadratrasferta: String, golsquadratrasferta: Int) { self.stagione = stagione self.giornata = giornata self.datapartita = datapartita self.squadracasa = squadracasa self.golsquadracasa = golsquadracasa self.squadratrasferta = squadratrasferta self.golsquadratrasferta = golsquadratrasferta } static func testCalendario() -> [CalendarioPartite] { [CalendarioPartite(stagione: "2023/2024", giornata: 1, datapartita: "04/09/2023", squadracasa: "Castelnovese Castelnuovo", golsquadracasa: 1, squadratrasferta: "Junior Asca", golsquadratrasferta: 3), .. } } This is representing the data structure of 4 different days in a football league with teams and results. Now I'd like to build a view where the four different days are displayed according to a grid layout. Therefore I started to build the grid item for a single day. And this works as expected. The tricky part is then to use this as a function to be displayed into a LazyVGrid layout so that all the four days are displayed. I'm struggling with this in the view file: import SwiftUI struct CalendarioView: View { @State var Calendario: [CalendarioPartite] = CalendarioPartite.testCalendario() @State var stagione: String = "2023/2024" @State var totalePartite: Int = 4 private var giornate = Array(1...4) private let adaptiveColumn = [GridItem(.adaptive(minimum: 150))] var partiteCampionato: [CalendarioPartite] { CalendarioPartite.testCalendario().filter{ $0.stagione == stagione } } var body: some View { ScrollView { LazyVGrid(columns: adaptiveColumn, spacing: 20) { ForEach(giornate, id: \.self) { giornata in giornataDisplay() } } }.padding() } func giornataDisplay() { VStack { var partiteGiornata: [CalendarioPartite] { partiteCampionato.filter { $0.giornata = giornate } } Text("Giornata \(giornate)") .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/) .font(.headline) .foregroundColor(/*@START_MENU_TOKEN@*/.blue/*@END_MENU_TOKEN@*/) .padding() Grid { ForEach (partiteGiornata) { partita in GridRow { Text(partita.squadracasa) .gridCellAnchor(UnitPoint(x: 0, y: 0.5)) Text("-") Text(partita.squadratrasferta) .gridCellAnchor(UnitPoint(x: 0, y: 0.5)) Text("=") Text(partita.golsquadracasa, format: .number) Text("-") Text(partita.golsquadratrasferta, format: .number) } } } } .background(Color.gray.opacity(0.2)) .clipShape(RoundedRectangle(cornerRadius: 15, style: .circular)) } } In fact, I'm getting two different errors: "No exact matches in reference to static method 'buildExpression'" in correspondence to the call of the function within the ForEach "Cannot assign to property: 'giornata' is a 'let' constant" within the function where I'm filtering the data to the "giornata" value. I guess this is depending by the fact that "giornate" var is an array. Am I right? Can you please assist me in achieving my desired result? Thanks, A.
3
0
525
Apr ’24
Failed to product diagnostic error
Dear all, I have the following code in a view: import SwiftUI struct RosaView: View { @State var rosa: [Rosa] = Rosa.testRosa() @State private var apriNuovoGiocatore = false @State var stagione: String = "2023/2024" var rosaFiltrata: [Rosa] { Rosa.testRosa().filter { $0.stagione == stagione } } @State private var selezioneGiocatore: Rosa.ID? = nil @State private var ordine = [KeyPathComparator(\Rosa.ruoloGiocatore)] var body: some View { VStack(alignment: .leading) { Text("Stagione: \(stagione)") .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/) .font(.headline) .foregroundColor(/*@START_MENU_TOKEN@*/.blue/*@END_MENU_TOKEN@*/) .padding() Table(rosaFiltrata, selection: $selezioneGiocatore, sortOrder: $ordine) { TableColumn(Text("Nome").foregroundStyle(.blue), value: \.nomeGiocatore) TableColumn(Text("Cognome").foregroundStyle(.blue), value: \.cognomeGiocatore) TableColumn(Text("Ruolo").foregroundStyle(.blue), value: \.ruoloGiocatore) TableColumn(Text("Data di nascita").foregroundStyle(.blue), value: \.nascitaGiocatore) TableColumn(Text("Età").foregroundStyle(.blue)) { Rosa in Text("\(Rosa.etàGiocatore)") } } } .frame(width: 900, height: 400) .toolbar { Button { apriNuovoGiocatore = true } label: { Image(systemName: "person.badge.plus") .foregroundColor(/*@START_MENU_TOKEN@*/.blue/*@END_MENU_TOKEN@*/) } .sheet(isPresented: $apriNuovoGiocatore, content: { nuovoGiocatore() }) } .navigationTitle("Rosa") } } struct nuovoGiocatore: View { @Environment(\.dismiss) var dismiss @State var nomeNuovoGiocatore: String @State var cognomeNuovoGiocatore: String @State var nascitaNuovoGiocatore: String @State var ruoloNuovoGiocatore: String @State var etàNuovoGiocatore: Int var body: some View { NavigationStack { Form { TextField("Nome:", text: $nomeNuovoGiocatore) TextField("Cognome:", text: $cognomeNuovoGiocatore) } .navigationTitle("Nuovo giocatore") .toolbar { Button("Cancel") { dismiss() } Button("Aggiungi giocatore") { let nuovoGiocatore = Rosa(stagione: "2023/2024", nomeGiocatore: nomeNuovoGiocatore, cognomeGiocatore: cognomeNuovoGiocatore, nascitaGiocatore: nascitaNuovoGiocatore, etàGiocatore: etàNuovoGiocatore, ruoloGiocatore: ruoloNuovoGiocatore) Rosa.testRosa().append(nuovoGiocatore) dismiss() } } } } } #Preview { RosaView() } On this, I'm getting a strange error which is "Failed to produce diagnostic for expression; please submit a bug report (https://swift.org/contributing/#reporting-bugs)" in the "var body: some View" statement of the view "nuovoGiocatore". How can I avoid it? Am I doing something wrong in the coding? Thanks, A.
4
0
869
Mar ’24
List half of an array
Dear all, I have initialized an array of a variable number of items @State private var squadre: [Squadre] = Squadre.test() Now, I'm showing in the following way the array: List { ForEach(squadre) { squadre in HStack { Text(squadre.squadra) Text("\(squadre.punti)") } } } I'd like to perform the following actions: Sort the array by the value "punti" (Int type) Show only the first half of the array in the list Do you have clue of how I can achieve it? I tried indexing the array, but didn't make it. Please support me. Thanks, A.
4
0
527
Mar ’24
LineMark chart reverting Y axis
Dear all, I have a line chart and on the Y axis it shows values from 0 (bottom) to 20 (top). Now, I'd like to show value from 20 (bottom) to 1 (top). Here below the code I used: Chart{ ForEach(andamento, id: \.posizione) { item in LineMark( x: .value("Giornata", item.giornata), y: .value("Posizione", item.posizione) ) PointMark( x: .value("Giornata", item.giornata), y: .value("Posizione", item.posizione) ) // We need .opacity(0) or it will // overlay your `.symbol` .opacity(0) .annotation(position: .overlay, alignment: .bottom, spacing: 10) { Text("\(item.posizione)") .font(.subheadline) } } .symbol(Circle()) } Can anybody help me? Thanks, A.
2
0
657
Mar ’24
SectorMark foreground style colors
Dear all, I am using SwiftUI 15.2 and I have created a donut chart using SectorMark. Now, I have three values to show in the chart. When I set up the foregroundstyle, it returns orange, blu and green colors, whereas I'd like to have different colors (e.g. red, yellow and green). Chart(data, id: \.risultato) { dataItem in SectorMark(angle: .value("Type", dataItem.partite), innerRadius: .ratio(0.7), angularInset: 1.5) .foregroundStyle(by: .value("Type", dataItem.risultato)) .annotation(position: .overlay){ Text("\(dataItem.partite)") .font(.caption) } } .frame(height: 150) I'm reporting the final result here below. Do you know how I can customize them? Thanks in advance for your support, Andrea
2
1
1.5k
Feb ’24