Le Regole dell'Esame di Teoria Patente B nel 2026
L'esame di teoria per la patente B presso la Motorizzazione Civile prevede:
- 30 domande VERO/FALSO estratte casualmente dal database ministeriale ufficiale.
- Tempo a disposizione: 20 minuti.
- Numero massimo di errori consentiti: 3 errori (con 4 o più errori l'esame è respinto).
Sviluppo Tecnico: Come Creare un'App Quiz Patente in SwiftUI
Ecco l'architettura completa per un motore di quiz in SwiftUI con gestione dello stato delle risposte e timer con countdown animato:
import SwiftUI
struct QuizQuestion: Identifiable {
let id = UUID()
let text: String
let imageName: String?
let isCorrect: Bool
var selectedAnswer: Bool? = nil
}
@Observable
final class PatenteQuizEngine {
var questions: [QuizQuestion] = []
var currentIndex: Int = 0
var timeRemaining: Int = 1200 // 20 minuti in secondi
var isExamFinished: Bool = false
var errorsCount: Int {
questions.filter { q in
guard let selected = q.selectedAnswer else { return false }
return selected != q.isCorrect
}.count
}
var isPassed: Bool {
errorsCount <= 3
}
func answerCurrent(with answer: Bool) {
guard currentIndex < questions.count else { return }
questions[currentIndex].selectedAnswer = answer
if currentIndex < questions.count - 1 {
currentIndex += 1
} else {
finishExam()
}
}
func finishExam() {
isExamFinished = true
}
}
struct PatenteQuizView: View {
@State private var engine = PatenteQuizEngine()
var body: some View {
VStack(spacing: 20) {
// Header con Timer ed Errori
HStack {
Text("Errori: \(engine.errorsCount)/3")
.font(.headline)
.foregroundStyle(engine.errorsCount > 3 ? .red : .green)
Spacer()
Text(timeString(from: engine.timeRemaining))
.font(.title3.monospacedDigit())
.fontWeight(.bold)
}
.padding()
if !engine.isExamFinished && engine.currentIndex < engine.questions.count {
let q = engine.questions[engine.currentIndex]
VStack(alignment: .leading, spacing: 16) {
Text("Domanda \(engine.currentIndex + 1) di \(engine.questions.count)")
.font(.caption)
.foregroundStyle(.secondary)
Text(q.text)
.font(.title3)
.fontWeight(.semibold)
.padding(.vertical)
HStack(spacing: 16) {
Button(action: { engine.answerCurrent(with: true) }) {
Text("VERO")
.font(.headline)
.frame(maxWidth: .infinity)
.padding()
.background(Color.green.opacity(0.15))
.foregroundStyle(.green)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
Button(action: { engine.answerCurrent(with: false) }) {
Text("FALSO")
.font(.headline)
.frame(maxWidth: .infinity)
.padding()
.background(Color.red.opacity(0.15))
.foregroundStyle(.red)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
}
.padding()
.background(Color(.secondarySystemBackground))
.clipShape(RoundedRectangle(cornerRadius: 16))
} else {
VStack(spacing: 16) {
Image(systemName: engine.isPassed ? "checkmark.seal.fill" : "xmark.octagon.fill")
.font(.system(size: 64))
.foregroundStyle(engine.isPassed ? .green : .red)
Text(engine.isPassed ? "PROMOSSO! 🎉" : "BOCCIATO 😭")
.font(.title)
.fontWeight(.bold)
Text("Hai commesso \(engine.errorsCount) errori (limite massimo: 3)")
.foregroundStyle(.secondary)
}
.padding()
}
Spacer()
}
.padding()
}
private func timeString(from totalSeconds: Int) -> String {
let min = totalSeconds / 60
let sec = totalSeconds % 60
return String(format: "%02d:%02d", min, sec)
}
}
Vuoi creare la tua App o hai bisogno di consulenza personalizzata?
Sviluppo app iOS native in SwiftUI, piattaforme backend scalabili e offro supporto strategico per monetizzazione e progetti internazionali.