# .reportWidth() ...

## 主要功能

* view.**reportWidth**(to: key)\
  回報自己的**寬度** (geometry.size.width) 給 `key` ([PreferenceKey](../../preferencekey))。\

* view.**reportFrame**(to: key, in: space)\
  回報自己的 geometry.**frame**(in: space) 給 `key`。

{% tabs %}
{% tab title="🌀View + pref" %}
```swift
import SwiftUI

// 🌀View + pref (generic methods)
extension View {
    
    // ⭐️ 回報 GeometryProxy 的屬性給 `key`
    //    - view.report(to: key) { $0.size }
    public func report<K: PreferenceKey>(
        
        // 要回報的對象 (PreferenceKey)
        to key: K.Type = K.self,
        
        // 要回報 GeometryProxy 的哪個屬性？
        // ⚠️ 注意：
        //    這裡的 `value` closure 必須標註為 `@escaping`，
        //    因為它用在 GeometryReader 的 @ViewBuilder closure 裡面，
        //    而這個 closure 本身就是 `@escaping`，所以如果沒有標註的話，
        //    會產生 "escaping closure captures non-escaping parameter" 的錯誤 ‼️
        value : @escaping (GeometryProxy) -> K.Value
        
    ) -> some View {
        self
            // ⭐️ 1. read self's geometry
            .background(GeometryReader { geo in  
                Color.clear
                    // ⭐️ 2. set preference:
                    //       report geo's attribute to `key`
                    .preference(key: key, value: value(geo))
            })
    }
    
    // view.register(to: key) { $0.frame(in: space) } 
    // T：收集的個別資料型別
    // K：PreferenceKey, K.Value == [T]
    public func register<T, K: PreferenceKey>(
        to key: K.Type = K.self, 
        value : @escaping (GeometryProxy) -> K.Value.Element
    ) -> some View 
        where K.Value == Array<T>  // ⭐️ 收集到 K.Value == [T]
    {
        self
            // ⭐️ 1. read self's geometry
            .background(GeometryReader { geo in  
                Color.clear
                    // ⭐️ 2. set preference:
                    //       (register geo's value to `key`)
                    .preference(key: key, value: [value(geo)])
            })
    }
    
}

// specialized methods
extension View {
    
    // report width
    // view.reportWidth(to: key)
    public func reportWidth<K: PreferenceKey>(
        to key: K.Type = K.self
    ) -> some View 
        where K.Value == CGFloat? 
    { 
        self.report(to: key) { $0.size.width } 
    }
    
    // report frame
    // view.reportFrame(to: key, in: space)
    public func reportFrame<K: PreferenceKey>(
        to key: K.Type = K.self, 
        in  space: CoordinateSpace = .global
    ) -> some View 
        where K.Value == CGRect? 
    { 
        self.report(to: key) { $0.frame(in: space) } 
    }
    
    // register frame
    // view.registerFrame(to: key, in space)
    public func registerFrame<K: PreferenceKey>(
        to key: K.Type = K.self, 
        in  space: CoordinateSpace = .global
    ) -> some View 
        where K.Value == [CGRect]
    { 
        self.register(to: key) { $0.frame(in: space) } 
    }
    
}
```
{% endtab %}

{% tab title="🌀  View + anchor pref" %}
```swift
import SwiftUI

// 🌀View + anchor preference (generic methods)
extension View {
    
    // view.register(to: FrameAnchors.self)
    public func register<K: PreferenceKey>(to key: K.Type = K.self) -> some View 
        where K.Value == [Anchor<CGRect>]
    {
        self.anchorPreference(key: K.self, value: .bounds) { [$0] }
    }
    
    // view.overlay(with: FrameAnchors.self) { anchors in ... }
    public func overlay<K: PreferenceKey, T: View>(
        with  key: K.Type = K.self, 
        transform: @escaping (K.Value) -> T
    ) -> some View 
        where K.Value == [Anchor<CGRect>]
    {
        overlayPreferenceValue(key) { transform($0) } 
    }
    
}
```
{% endtab %}

{% tab title="📘 參考 " %}
* [x] [The magic of view preferences in SwiftUI](https://swiftwithmajid.com/2020/01/15/the-magic-of-view-preferences-in-swiftui/) - Swift with Majid
* [x] [Inspecting the View Tree – Part 1: PreferenceKey](https://swiftui-lab.com/communicating-with-the-view-tree-part-1/) - The SwiftUI Lab  ⭐️
* [x] [Inspecting the View Tree – Part 2: AnchorPreferences](https://swiftui-lab.com/communicating-with-the-view-tree-part-2/) - The SwiftUI Lab
{% endtab %}

{% tab title="👥  相關 " %}
* [🅿️ PreferenceKey](../../preferencekey)
* [Preferences](broken-reference)
* [🌅  GeometryReader](../../../../view/measure/geometryreader)
* [🌅 對齊欄位]()
* [💈 MonthView](../../../../../master/todo/exercises/monthview)
{% endtab %}
{% endtabs %}
