Bird
Raised Fist0
iOS Swiftmobile~20 mins

Preference keys in iOS Swift - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Preference Key Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ ui_behavior
intermediate
2:00remaining
What is the output of this SwiftUI PreferenceKey example?
Consider this SwiftUI code that uses a custom PreferenceKey to pass a value up the view tree. What will be printed in the console when the button is tapped?
iOS Swift
struct MyPreferenceKey: PreferenceKey {
  static var defaultValue: Int = 0
  static func reduce(value: inout Int, nextValue: () -> Int) {
    value += nextValue()
  }
}

struct ContentView: View {
  @State private var total = 0
  var body: some View {
    VStack {
      Text("Total: \(total)")
      Button("Tap me") {}
        .preference(key: MyPreferenceKey.self, value: 3)
    }
    .onPreferenceChange(MyPreferenceKey.self) { value in
      print("Preference value changed to \(value)")
      total = value
    }
  }
}
APreference value changed to 3\nTotal: 3
BPreference value changed to 0\nTotal: 0
CPreference value changed to 6\nTotal: 6
DNo output printed; total remains 0
Attempts:
2 left
💡 Hint
Remember that the reduce function sums all values from children views.
❓ lifecycle
intermediate
1:30remaining
When is the reduce function of a PreferenceKey called?
In SwiftUI, the reduce(value:nextValue:) method of a PreferenceKey is called at which point during the view update cycle?
ABefore any child views set their preference values
BAfter all child views have set their preference values, before the parent reads them
COnly when the parent view appears on screen
DEvery time the parent view's body is recomputed
Attempts:
2 left
💡 Hint
Think about how preferences aggregate values from children.
📝 Syntax
advanced
2:30remaining
Which option correctly defines a PreferenceKey with a String default value?
Select the correct Swift code that defines a PreferenceKey with a default value of an empty string and concatenates child values.
A
struct StringPreferenceKey: PreferenceKey {
  static var defaultValue = ""
  static func reduce(value: String, nextValue: () -> String) {
    value += nextValue()
  }
}
B
struct StringPreferenceKey: PreferenceKey {
  static var defaultValue: String? = nil
  static func reduce(value: inout String, nextValue: () -> String) {
    value = nextValue()
  }
}
C
struct StringPreferenceKey: PreferenceKey {
  static var defaultValue: String = ""
  static func reduce(value: inout String, nextValue: () -> String) {
    value += nextValue()
  }
}
D
struct StringPreferenceKey: PreferenceKey {
  static var defaultValue: String = ""
  func reduce(value: inout String, nextValue: () -> String) {
    value += nextValue()
  }
}
Attempts:
2 left
💡 Hint
Check the method signature and static properties required by PreferenceKey protocol.
🔧 Debug
advanced
2:30remaining
Why does this PreferenceKey not update the parent view?
Given this code, why does the parent view not update when the child sets a preference value? struct MyKey: PreferenceKey { static var defaultValue: Int = 0 static func reduce(value: inout Int, nextValue: () -> Int) { value = nextValue() } } struct ParentView: View { @State private var number = 0 var body: some View { ChildView() .onPreferenceChange(MyKey.self) { value in number = value } Text("Number: \(number)") } } struct ChildView: View { var body: some View { Text("Child") .preference(key: MyKey.self, value: 5) } }
AThe onPreferenceChange modifier is attached to ChildView, so it never receives the preference from ChildView itself.
BThe preference key's defaultValue is zero, so the preference never changes from default.
CThe ParentView's body does not include the Text displaying number inside the VStack or container, so it won't update properly.
DThe reduce function overwrites value instead of combining, so multiple children values are lost, but here only one child exists, so this is not the issue.
Attempts:
2 left
💡 Hint
Consider where onPreferenceChange is applied in the view hierarchy.
🧠 Conceptual
expert
1:30remaining
What is the main purpose of PreferenceKey in SwiftUI?
Which statement best describes the main use of PreferenceKey in SwiftUI?
ATo define custom animations for view transitions
BTo store user preferences persistently across app launches
CTo manage state locally within a single view without affecting others
DTo allow child views to communicate values up the view hierarchy to parent views in a decoupled way
Attempts:
2 left
💡 Hint
Think about data flow direction and how PreferenceKey helps views communicate.

Practice

(1/5)
1. What is the main purpose of PreferenceKey in SwiftUI?
easy
A. To store user preferences permanently
B. To share simple data up the view hierarchy
C. To create custom buttons
D. To manage network requests

Solution

  1. Step 1: Understand PreferenceKey role

    PreferenceKey is designed to pass data from child views up to parent views in SwiftUI.
  2. Step 2: Differentiate from other uses

    It is not for permanent storage or UI elements but for sharing layout or state info upwards.
  3. Final Answer:

    To share simple data up the view hierarchy -> Option B
  4. Quick Check:

    PreferenceKey = share data up [OK]
Hint: PreferenceKey passes data upward, not stores or creates UI [OK]
Common Mistakes:
  • Confusing PreferenceKey with UserDefaults
  • Thinking it creates UI components
  • Assuming it manages network tasks
2. Which of the following is the correct way to declare a PreferenceKey with a default value of 0 and a reduce function that sums values?
easy
A. struct MyKey: PreferenceKey { static var defaultValue = 0; static func reduce(value: Int, nextValue: () -> Int) { value += nextValue() } }
B. struct MyKey: PreferenceKey { static let defaultValue = 0; static func reduce(value: Int, nextValue: () -> Int) { value += nextValue() } }
C. struct MyKey: PreferenceKey { var defaultValue: Int = 0; func reduce(value: inout Int, nextValue: () -> Int) { value += nextValue() } }
D. struct MyKey: PreferenceKey { static var defaultValue: Int = 0; static func reduce(value: inout Int, nextValue: () -> Int) { value += nextValue() } }

Solution

  1. Step 1: Check static defaultValue declaration

    It must be a static property with explicit type: static var defaultValue: Int = 0.
  2. Step 2: Verify reduce function signature

    Reduce must be static, take inout value, and add nextValue: static func reduce(value: inout Int, nextValue: () -> Int).
  3. Final Answer:

    struct MyKey: PreferenceKey { static var defaultValue: Int = 0; static func reduce(value: inout Int, nextValue: () -> Int) { value += nextValue() } } -> Option D
  4. Quick Check:

    Static defaultValue and reduce with inout = struct MyKey: PreferenceKey { static var defaultValue: Int = 0; static func reduce(value: inout Int, nextValue: () -> Int) { value += nextValue() } } [OK]
Hint: defaultValue and reduce must be static with correct signatures [OK]
Common Mistakes:
  • Missing static keyword on defaultValue or reduce
  • Using var instead of static var for defaultValue
  • Incorrect reduce function parameters
3. Given this code snippet, what will be printed?
struct CountKey: PreferenceKey {
  static var defaultValue = 0
  static func reduce(value: inout Int, nextValue: () -> Int) {
    value += nextValue()
  }
}

struct ContentView: View {
  var body: some View {
    VStack {
      Text("Hello").preference(key: CountKey.self, value: 1)
      Text("World").preference(key: CountKey.self, value: 2)
    }
    .onPreferenceChange(CountKey.self) { print($0) }
  }
}
medium
A. 3
B. 2
C. 1
D. 0

Solution

  1. Step 1: Understand preference values set

    Two Text views set preferences with values 1 and 2 respectively.
  2. Step 2: Apply reduce function logic

    Reduce sums values: 0 (default) + 1 + 2 = 3.
  3. Final Answer:

    3 -> Option A
  4. Quick Check:

    Sum of preferences = 3 [OK]
Hint: Reduce sums all values, so 1 + 2 = 3 [OK]
Common Mistakes:
  • Assuming only last value is used
  • Ignoring reduce function behavior
  • Confusing defaultValue with output
4. Identify the error in this PreferenceKey implementation:
struct SizeKey: PreferenceKey {
  static var defaultValue: CGSize = .zero
  static func reduce(value: CGSize, nextValue: () -> CGSize) {
    value = nextValue()
  }
}
medium
A. reduce function must have inout parameter for value
B. defaultValue must be non-static
C. nextValue must return Int, not CGSize
D. PreferenceKey cannot use CGSize type

Solution

  1. Step 1: Check defaultValue declaration

    defaultValue is correctly static with CGSize type.
  2. Step 2: Inspect reduce function signature

    Reduce must take inout for value to modify it, but here it is a value parameter.
  3. Final Answer:

    reduce function must have inout parameter for value -> Option A
  4. Quick Check:

    Reduce needs inout value parameter [OK]
Hint: Reduce must use inout for value to update it [OK]
Common Mistakes:
  • Forgetting inout keyword in reduce
  • Changing defaultValue to non-static
  • Wrong return type for nextValue
5. You want to pass the maximum width of child views up to a parent using PreferenceKey. Which implementation correctly combines widths to find the maximum?
hard
A. struct MaxWidthKey: PreferenceKey { static var defaultValue: CGFloat = 0 static func reduce(value: CGFloat, nextValue: () -> CGFloat) { value = max(value, nextValue()) } }
B. struct MaxWidthKey: PreferenceKey { static var defaultValue: CGFloat = 0 static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value += nextValue() } }
C. struct MaxWidthKey: PreferenceKey { static var defaultValue: CGFloat = 0 static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = max(value, nextValue()) } }
D. struct MaxWidthKey: PreferenceKey { static var defaultValue: CGFloat = 0 static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = min(value, nextValue()) } }

Solution

  1. Step 1: Identify correct reduce logic for max

    To find maximum width, reduce must assign the max of current and next values.
  2. Step 2: Verify function signature and logic

    Reduce must be static, take inout value, and use value = max(value, nextValue()).
  3. Final Answer:

    struct MaxWidthKey: PreferenceKey { static var defaultValue: CGFloat = 0; static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = max(value, nextValue()) } } -> Option C
  4. Quick Check:

    Use max in reduce with inout value [OK]
Hint: Use max function and inout value in reduce [OK]
Common Mistakes:
  • Using sum (+) instead of max
  • Missing inout in reduce parameter
  • Using min instead of max
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard