Agent skills for iOS, iPadOS, Swift, SwiftUI, and modern Apple framework development.
71
89%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Overflow reference for the energykit skill. Contains advanced patterns
that exceed the main skill file's scope.
An @Observable manager that ties together guidance, venues, and load events.
import EnergyKit
import SwiftUI
@Observable
@MainActor
final class EnergyManager {
var venues: [EnergyVenue] = []
var selectedVenue: EnergyVenue?
var currentGuidance: ElectricityGuidance?
var guidanceValues: [ElectricityGuidance.Value] = []
var isLoading = false
var errorMessage: String?
private var guidanceTask: Task<Void, Never>?
func loadVenues() async {
isLoading = true
errorMessage = nil
do {
venues = try await EnergyVenue.venues()
selectedVenue = venues.first
if let venue = selectedVenue {
startObservingGuidance(for: venue.id)
}
} catch let error as EnergyKitError {
errorMessage = handleError(error)
} catch {
errorMessage = error.localizedDescription
}
isLoading = false
}
func startObservingGuidance(for venueID: UUID) {
guidanceTask?.cancel()
guidanceTask = Task { [weak self] in
let query = ElectricityGuidance.Query(suggestedAction: .shift)
let service = ElectricityGuidance.sharedService
do {
for try await guidance in service.guidance(using: query, at: venueID) {
self?.currentGuidance = guidance
self?.guidanceValues = guidance.values
}
} catch {
self?.errorMessage = error.localizedDescription
}
}
}
func stopObserving() {
guidanceTask?.cancel()
guidanceTask = nil
}
var bestWindow: ElectricityGuidance.Value? {
guidanceValues.min(by: { $0.rating < $1.rating })
}
var hasRatePlan: Bool {
currentGuidance?.options.contains(.locationHasRatePlan) ?? false
}
var usesRatePlan: Bool {
currentGuidance?.options.contains(.guidanceIncorporatesRatePlan) ?? false
}
// EnergyKitError cases
private func handleError(_ error: EnergyKitError) -> String {
switch error {
case .unsupportedRegion:
return "Energy guidance is not available in your region."
case .guidanceUnavailable:
return "Grid guidance data is currently unavailable."
case .venueUnavailable:
return "No energy venue found. Set up your home in the Home app."
case .permissionDenied:
return "Permission to access energy data was denied."
case .serviceUnavailable:
return "The energy service is temporarily unavailable."
case .rateLimitExceeded:
return "Too many requests. Please try again later."
case .invalidLoadEvent:
return "The load event data was invalid."
case .inProgress:
return "A request is already in progress."
case .locationServicesDenied:
return "Location services are required for energy guidance."
@unknown default:
return "An unknown error occurred."
}
}
}Manage the full lifecycle of an EV charging session with guidance tracking.
import EnergyKit
@Observable
@MainActor
final class EVChargingManager {
var isCharging = false
var currentSessionID: UUID?
var stateOfCharge: Int = 0
var currentPower: Double = 0 // kW
var totalEnergy: Double = 0 // kWh
private let deviceID: String
private var venue: EnergyVenue?
private var guidanceToken: UUID?
init(deviceID: String) {
self.deviceID = deviceID
}
func setVenue(_ venue: EnergyVenue) {
self.venue = venue
}
func setGuidanceToken(_ token: UUID) {
self.guidanceToken = token
}
func startCharging(stateOfCharge: Int) async throws {
guard let venue else { throw EVError.noVenue }
let sessionID = UUID()
currentSessionID = sessionID
self.stateOfCharge = stateOfCharge
isCharging = true
let event = makeEvent(
sessionState: .begin,
stateOfCharge: stateOfCharge,
power: 0,
energy: 0
)
try await venue.submitEvents([event])
}
func updateCharging(
stateOfCharge: Int,
power: Double,
energy: Double
) async throws {
guard let venue, isCharging else { return }
self.stateOfCharge = stateOfCharge
self.currentPower = power
self.totalEnergy = energy
let event = makeEvent(
sessionState: .active,
stateOfCharge: stateOfCharge,
power: power,
energy: energy
)
try await venue.submitEvents([event])
}
func stopCharging() async throws {
guard let venue, isCharging else { return }
let event = makeEvent(
sessionState: .end,
stateOfCharge: stateOfCharge,
power: 0,
energy: totalEnergy
)
try await venue.submitEvents([event])
isCharging = false
currentSessionID = nil
}
private func makeEvent(
sessionState: ElectricVehicleLoadEvent.Session.State,
stateOfCharge: Int,
power: Double,
energy: Double
) -> ElectricVehicleLoadEvent {
let guidanceState = ElectricVehicleLoadEvent.Session.GuidanceState(
wasFollowingGuidance: guidanceToken != nil,
guidanceToken: guidanceToken ?? UUID()
)
let session = ElectricVehicleLoadEvent.Session(
id: currentSessionID ?? UUID(),
state: sessionState,
guidanceState: guidanceState
)
let measurement = ElectricVehicleLoadEvent.ElectricalMeasurement(
stateOfCharge: stateOfCharge,
direction: .imported,
power: Measurement(value: power, unit: .kilowatts),
energy: Measurement(value: energy, unit: .kilowattHours)
)
return ElectricVehicleLoadEvent(
timestamp: Date(),
measurement: measurement,
session: session,
deviceID: deviceID
)
}
enum EVError: Error {
case noVenue
}
}Track HVAC load events with guidance compliance.
import EnergyKit
@Observable
@MainActor
final class HVACManager {
var isRunning = false
var currentStage: Int = 0
var sessionID: UUID?
private let deviceID: String
private var venue: EnergyVenue?
private var guidanceToken: UUID?
init(deviceID: String) {
self.deviceID = deviceID
}
func configure(venue: EnergyVenue, guidanceToken: UUID?) {
self.venue = venue
self.guidanceToken = guidanceToken
}
func start(stage: Int) async throws {
guard let venue else { return }
sessionID = UUID()
currentStage = stage
isRunning = true
let event = makeEvent(state: .begin, stage: stage)
try await venue.submitEvents([event])
}
func updateStage(_ stage: Int) async throws {
guard let venue, isRunning else { return }
currentStage = stage
let event = makeEvent(state: .active, stage: stage)
try await venue.submitEvents([event])
}
func stop() async throws {
guard let venue, isRunning else { return }
let event = makeEvent(state: .end, stage: 0)
try await venue.submitEvents([event])
isRunning = false
sessionID = nil
}
private func makeEvent(
state: ElectricHVACLoadEvent.Session.State,
stage: Int
) -> ElectricHVACLoadEvent {
let guidanceState = ElectricHVACLoadEvent.Session.GuidanceState(
wasFollowingGuidance: guidanceToken != nil,
guidanceToken: guidanceToken ?? UUID()
)
let session = ElectricHVACLoadEvent.Session(
id: sessionID ?? UUID(),
state: state,
guidanceState: guidanceState
)
let measurement = ElectricHVACLoadEvent.ElectricalMeasurement(stage: stage)
return ElectricHVACLoadEvent(
timestamp: Date(),
measurement: measurement,
session: session,
deviceID: deviceID
)
}
}A complete dashboard view showing guidance and insights.
import SwiftUI
import EnergyKit
struct EnergyDashboardView: View {
@Environment(EnergyManager.self) private var energyManager
var body: some View {
NavigationStack {
Group {
if energyManager.isLoading {
ProgressView("Loading energy data...")
} else if let error = energyManager.errorMessage {
ContentUnavailableView(
"Energy Guidance Unavailable",
systemImage: "bolt.slash",
description: Text(error)
)
} else {
dashboardContent
}
}
.navigationTitle("Energy")
.task {
await energyManager.loadVenues()
}
}
}
private var dashboardContent: some View {
List {
if let venue = energyManager.selectedVenue {
Section("Venue") {
LabeledContent("Name", value: venue.name)
}
}
if let best = energyManager.bestWindow {
Section("Best Time") {
VStack(alignment: .leading) {
Text("Optimal usage window")
.font(.headline)
Text(best.interval.start, style: .time)
+ Text(" - ")
+ Text(best.interval.end, style: .time)
Text("Rating: \(best.rating, specifier: "%.2f")")
.foregroundStyle(.secondary)
}
}
}
if !energyManager.guidanceValues.isEmpty {
Section("Timeline") {
ForEach(energyManager.guidanceValues, id: \.interval.start) { value in
HStack {
VStack(alignment: .leading) {
Text(value.interval.start, style: .time)
Text(value.interval.end, style: .time)
.font(.caption)
.foregroundStyle(.secondary)
}
Spacer()
guidanceRatingView(value.rating)
}
}
}
}
if energyManager.hasRatePlan {
Section("Rate Plan") {
Label(
energyManager.usesRatePlan
? "Guidance incorporates your rate plan"
: "Rate plan available but not yet incorporated",
systemImage: "dollarsign.circle"
)
}
}
}
}
private func guidanceRatingView(_ rating: Double) -> some View {
let color: Color = rating <= 0.3 ? .green : rating <= 0.6 ? .yellow : .red
let label = rating <= 0.3 ? "Good" : rating <= 0.6 ? "Fair" : "Avoid"
return Text(label)
.font(.caption)
.fontWeight(.medium)
.padding(.horizontal)
.padding(.vertical)
.background(color.opacity(0.15))
.foregroundStyle(color)
.clipShape(Capsule())
}
}Prepare insight records for chart display.
struct InsightDataPoint: Identifiable {
let id = UUID()
let date: Date
let energy: Double // kWh
let cleanerEnergy: Double?
let lessCleanEnergy: Double?
}
func processInsightRecords(
_ records: [ElectricityInsightRecord<Measurement<UnitEnergy>>]
) -> [InsightDataPoint] {
records.compactMap { record in
guard let total = record.totalEnergy else { return nil }
return InsightDataPoint(
date: record.range.start,
energy: total.converted(to: .kilowattHours).value,
cleanerEnergy: record.dataByGridCleanliness?.cleaner?
.converted(to: .kilowattHours).value,
lessCleanEnergy: record.dataByGridCleanliness?.lessClean?
.converted(to: .kilowattHours).value
)
}
}Comprehensive error handling with retry logic.
@Observable
@MainActor
final class ResilientEnergyService {
private let maxRetries = 3
func fetchGuidanceWithRetry(venueID: UUID) async throws -> ElectricityGuidance? {
let query = ElectricityGuidance.Query(suggestedAction: .shift)
let service = ElectricityGuidance.sharedService
for attempt in 0..<maxRetries {
do {
for try await guidance in service.guidance(using: query, at: venueID) {
return guidance
}
} catch let error as EnergyKitError {
switch error {
case .serviceUnavailable, .rateLimitExceeded:
if attempt < maxRetries - 1 {
try await Task.sleep(for: .seconds(pow(2.0, Double(attempt + 1))))
}
case .unsupportedRegion, .permissionDenied, .venueUnavailable:
throw error // Do not retry permanent failures
default:
throw error
}
}
}
return nil
}
}Guide users through venue setup if none exist.
import SwiftUI
import EnergyKit
struct VenueSetupView: View {
@State private var venues: [EnergyVenue] = []
@State private var isLoading = true
@State private var showSetupGuide = false
var body: some View {
Group {
if isLoading {
ProgressView()
} else if venues.isEmpty {
ContentUnavailableView {
Label("No Energy Venues", systemImage: "house")
} description: {
Text("Set up your home in the Home app to use energy guidance.")
} actions: {
Button("Learn More") { showSetupGuide = true }
.buttonStyle(.borderedProminent)
}
} else {
List(venues, id: \.id) { venue in
NavigationLink(value: venue.id) {
Label(venue.name, systemImage: "house.fill")
}
}
}
}
.task {
do {
venues = try await EnergyVenue.venues()
} catch {
venues = []
}
isLoading = false
}
}
}skills
accessorysetupkit
references
activitykit
references
adattributionkit
references
alarmkit
references
app-clips
app-intents
references
app-store-optimization
app-store-review
apple-on-device-ai
appmigrationkit
references
audioaccessorykit
references
authentication
references
avkit
references
background-processing
references
browserenginekit
references
callkit
references
carplay
references
cloudkit
references
contacts-framework
references
core-bluetooth
references
core-data
core-motion
references
core-nfc
references
coreml
references
cryptokit
references
cryptotokenkit
references
debugging-instruments
device-integrity
references
dockkit
references
energykit
references
eventkit
references
financekit
references
focus-engine
gamekit
references
healthkit
references
homekit
references
ios-accessibility
ios-localization
ios-networking
ios-simulator
references
mapkit
metrickit
references
musickit
references
natural-language
references
paperkit
references
passkit
references
pdfkit
references
pencilkit
references
permissionkit
references
photokit
push-notifications
realitykit
references
relevancekit
references
scenekit
references
sensorkit
references
speech-recognition
spritekit
references
storekit
swift-api-design-guidelines
swift-architecture
swift-charts
references
swift-codable
swift-concurrency
swift-formatstyle
swift-language
swift-security
references
swift-testing
swiftdata
swiftlint
swiftui-animation
swiftui-gestures
references
swiftui-layout-components
swiftui-liquid-glass
references
swiftui-patterns
swiftui-performance
swiftui-uikit-interop
swiftui-webkit
tabletopkit
references
tipkit
references
vision-framework
weatherkit
references
widgetkit
references