Skip to content

Instantly share code, notes, and snippets.

@kylebshr
Last active February 10, 2025 21:48
Show Gist options
  • Save kylebshr/0f94d216994e33dedf8c2b45a286add2 to your computer and use it in GitHub Desktop.
Save kylebshr/0f94d216994e33dedf8c2b45a286add2 to your computer and use it in GitHub Desktop.
How to conditionally build widget configuration parameters based on UserDefaults or other conditions
//
// ConditionalDefaultEntity.swift
// Mercury
//
// Created by Kyle Bashour on 2/10/25.
// Copyright © 2025 Kyle Bashour. All rights reserved.
//
import AppIntents
/// Provides a way to conditionally build widget configuration parameters based on "external" values.
///
/// You can't use if statements or other conditions inside the result builders, but you can query
/// whether an entity exists. This is a bit of a hack that conditionally provides a default entity
/// based on value returned from a closure, so you can read a boolean value out of something like
/// UserDefaults, Keychain, or elsewhere.
@available(iOS 17, *)
struct ConditionalDefaultEntity: AppEntity {
static let typeDisplayRepresentation: TypeDisplayRepresentation = "Has queried value"
static let defaultQuery = ConditionalDefaultEntityQuery()
let displayRepresentation = DisplayRepresentation(title: "Has queried value")
let id: UUID
init(id: UUID) {
self.id = UUID()
}
}
@available(iOS 17, *)
struct ConditionalDefaultEntityQuery: EntityQuery {
let valueProvider: @Sendable () -> Bool
init() {
valueProvider = { false }
}
init(valueProvider: @escaping @Sendable () -> Bool) {
self.valueProvider = valueProvider
}
func entities(for identifiers: [ConditionalDefaultEntity.ID]) async throws -> [ConditionalDefaultEntity] {
identifiers.map { ConditionalDefaultEntity(id: $0) }
}
func defaultResult() async -> ConditionalDefaultEntity? {
valueProvider() ? ConditionalDefaultEntity(id: UUID()) : nil
}
}
//
// ExampleWidgetIntent.swift
// MercuryWidgetExtension
//
// Created by Kyle Bashour on 2/10/25.
// Copyright © 2025 Kyle Bashour. All rights reserved.
//
import AppIntents
import WidgetKit
@available(iOS 17, *)
struct ExampleWidgetIntent: WidgetConfigurationIntent {
static var title: LocalizedStringResource = "My cool widget"
static var isDiscoverable: Bool = false
@Parameter(
title: "Is value true",
query: ConditionalDefaultEntityQuery {
UserDefaults.standard.bool(forKey: "my-cool-value")
}
)
var isValueTrue: ConditionalDefaultEntity?
@Parameter(title: "Relevant if value is true")
var trueRelevantValue: MyEntity?
@Parameter(title: "Relevant if value is false")
var falseRelevantValue: MyOtherEntity?
static var parameterSummary: some ParameterSummary {
When(\.$isValueTrue, .hasAnyValue) {
Summary {
\.$trueRelevantValue
}
} otherwise: {
Summary {
\.$falseRelevantValue
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment