Exploring Journaling Suggestions: Emotions and Moods with State of Mind
After covering Reflection Prompts, I decided to talk about State of Mind suggestion for journaling.
Exploring Journaling Suggestions: Adding Reflection Prompt
Understanding JournalingSuggestion.StateOfMind
Apple introduced the JournalingSuggestion.StateOfMind structure in iOS 18.0 (currently in beta). It captures a person's emotional state in a journaling app.
Here is what the structure looks like:
/// A suggestion that describes a state of mind reflection in the Health app.
@available(iOS 18.0, *)
public struct StateOfMind : JournalingSuggestionAsset { }This structure comes with some useful properties:
darkBackground: An optionalGradientfor dark mode icons.lightBackground: An optionalGradientfor light mode icons.icon: A URL to an image that represents the mood.state: The actual state of mind, stored as anHKStateOfMindobject.
I have already covered HKStateOfMind in detail here:
Exploring HealthKit: Working with State of Mind APIs
The system gives your app an instance of this structure when someone picks a state of mind suggestion in the JournalingSuggestionsPicker.
Implementing State of Mind Suggestions
Let's look at how you can use this in your app:
import JournalingSuggestions
import SwiftUI
import HealthKit
@available(iOS 18.0, *)
struct StateOfMindView: View {
@State private var stateOfMind: JournalingSuggestion.StateOfMind?
@State private var suggestionTitle: String?
var body: some View {
NavigationStack {
VStack {
if let stateOfMind = stateOfMind {
StateOfMindDisplayView(stateOfMind: stateOfMind)
}
JournalingSuggestionsPicker {
Text("How are you feeling?")
} onCompletion: { suggestion in
suggestionTitle = suggestion.title
Task {
stateOfMind = await suggestion.content(forType: JournalingSuggestion.StateOfMind.self).first
}
}
.buttonStyle(.borderedProminent)
}
.navigationTitle(suggestionTitle ?? "")
}
}
}This view includes a JournalingSuggestionsPicker to get new state of mind suggestions. When a user picks a suggestion, we update the stateOfMind property.
An interesting thing to note is how the system handles data from third-party apps. If a third-party app logs state of mind data, it shows up in the title. For example, you might see "Arising - Momentary Emotion" for my app called Arising that logged the mood data. This helps users understand where their mood data is coming from.
Next, let's create a view to display the state of mind related information:
import HealthKit
extension HKStateOfMind.ValenceClassification: @retroactive CustomStringConvertible {
public var description: String {
switch self {
case .veryUnpleasant: "Very Unpleasant"
case .unpleasant: "Unpleasant"
case .slightlyUnpleasant: "Slightly Unpleasant"
case .neutral: "Neutral"
case .slightlyPleasant: "Slightly Pleasant"
case .pleasant: "Pleasant"
case .veryPleasant: "Very Pleasant"
@unknown default: "Neautral"
}
}
}
@available(iOS 18.0, *)
struct StateOfMindDisplayView: View {
let stateOfMind: JournalingSuggestion.StateOfMind
var body: some View {
VStack {
if let iconURL = stateOfMind.icon {
AsyncImage(url: iconURL) { image in
image.resizable()
.scaledToFit()
} placeholder: {
ProgressView()
}
}
Text(stateOfMind.state.valenceClassification.description)
.font(.title)
.bold()
.multilineTextAlignment(.center)
.padding()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(backgroundGradient)
}
private var backgroundGradient: some View {
LinearGradient(
gradient: stateOfMind.lightBackground ?? Gradient(colors: [.white]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
}
}I added custom string representation for each mood state. This view shows the mood icon and uses the custom description for the state of mind.
When you tap "How are you feeling?", the system shows a picker interface. After selecting a mood, the onCompletionclosure runs with a JournalingSuggestion object. This object has the state of mind information.
Here is what a raw JournalingSuggestion object looks like:
JournalingSuggestions.JournalingSuggestion(items: [JournalingSuggestions.JournalingSuggestion.ItemContent(id: FE9C3C74-1AEA-4003-9BFD-5F0C58DC36C2, representations: [JournalingSuggestions.JournalingSuggestion.StateOfMind, SwiftUI.Image, UIImage], content: JournalingSuggestions.InternalAssetContent(providers: [JournalingSuggestions.InternalAssetContent.AssetProvider(type: JournalingSuggestions.JournalingSuggestion.StateOfMind, loader: (Function)), JournalingSuggestions.InternalAssetContent.AssetProvider(type: SwiftUI.Image, loader: (Function)), JournalingSuggestions.InternalAssetContent.AssetProvider(type: UIImage, loader: (Function))]))], title: "Arising — Momentary Emotion", date: Optional(2024-08-16 06:42:23 +0000 to 2024-08-16 06:42:23 +0000), suggestionIdentifier: AB5F68CD-D892-4873-9E24-606B3C887518, suggestionHashValue: 12941230080)Moving Forward
It is a bit annoying that the Health app notes are constrained when you log a new entry, but makes sense that it is not a journaling app. I guess that is where this journaling suggestions fills the gap.
Remember, this feature is still in beta for iOS 18.0. Keep an eye on Apple's documentation for any changes before the official release in September.
Happy coding and journaling!
Post Topics
Explore more in these categories: