SwiftUI中PreferenceKey协议的reduce方法何时需实现内容?空实现仍生效的原因解析
reduce method works for PreferenceKey, and when you need to implement it Let’s break this down clearly, based on how SwiftUI’s preference system works:
1. Your empty reduce works because no merging is needed
The reduce method of PreferenceKey only exists to merge multiple values sent from different child views for the same key.
In your current code, it’s almost certain that only a single view is setting the SizePreferenceKey or ViewOffsetKey value—like one ScrollView reporting its scroll offset, or one specific view reporting its size. When there’s only one value to process, SwiftUI doesn’t need to merge anything. It skips the reduce method entirely and uses that single value directly. That’s why your code runs perfectly even with an empty implementation.
2. When you must write concrete reduce logic
You need to fill in the reduce method whenever multiple views contribute values to the same preference key. Its job is to define how all those individual values should be combined into one final value that gets passed to onPreferenceChange.
For example:
- If you want to track the total height of a stack of views, you’d use
value += nextValue()to sum all their heights. - If you need the maximum width among several buttons, you’d write
value = max(value, nextValue()). - If you only care about the most recently updated value from any view, you could set
value = nextValue()to overwrite the current value with each new entry.
Without this logic, when multiple values exist, SwiftUI will either stick to the defaultValue or ignore all but one of the values—leading to incorrect or unexpected behavior.
3. Why onPreferenceChange still functions with an empty reduce
onPreferenceChange receives the final merged value from the preference system. When there’s only one source of the preference value, no merging step is required. SwiftUI sends that single value straight to your handler without ever calling reduce. The empty method is never invoked, so it doesn’t impact the result.
内容的提问来源于stack exchange,提问作者shingo.nakanishi

