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)
}
Post
Replies
Boosts
Views
Activity
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
...
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
Dear all,
I'm quite new to Xcode.
I'm trying to set up my first project - I'd like to create a macOS and iPad app.
So I'm following the steps in Xcode, but receiving errors.
I'm attaching the steps I'm following with the details of what Xcode is giving me as error.
C
o
Could you please give me indications on how to solve the issue?
Thanks,
Andrea