
Photo by Sébastien Goldberg on Unsplash
Mount Cook, Nouvelle-Zélande
期望實作這功能
RatingView 子視圖會告訴父視圖,Rating 給幾顆星⭐️。
發現之前招式
struct PublicSwimmingPoolDetailView: View {
    var publicSwimmingPool: PoolItem
}
// ------
PublicSwimmingPoolDetailView(publicSwimmingPool: item)
publicSwimmingPool 是 read-only property 🤔
研究一陣子開竅,需要 @Binding 新招式
@State
用於私有狀態管理。
主要用於視圖內部,當狀態變化時,視圖會重新渲染。
是值類型的存儲方式,當值改變時,只有與該值有關的視圖部分會被重新渲染。
例子:
@State private var isToggled: Bool = false
@Binding
這是一種參照某個其它狀態的方式。當你需要從一個視圖到另一個視圖共享同一狀態時,這非常有用。
它不擁有該狀態的真實存儲,而是提供一種方式來讀取和寫入該值。
例子:
@Binding var text: String
read-only property
struct ParentView: View {
    @State private var pool = PoolItem(name: "Community Pool")
    var body: some View {
        VStack {
            // ... 其他 UI ...
            PublicSwimmingPoolDetailView(publicSwimmingPool: pool)
        }
    }
}
struct PublicSwimmingPoolDetailView: View {
    var publicSwimmingPool: PoolItem
    var body: some View {
        // ... 使用 publicSwimmingPool ...
    }
}
視覺化解釋
struct RatingView: View {
    @Binding var rating: Int
    
    var label = ""
    var maximumRating = 5
    
    var offImage: Image?
    var onImage = Image(systemName: "star.fill")
    
    var offColor = Color.gray
    var onColor = Color.yellow
    
    var body: some View {
        HStack {
            if label.isEmpty == false {
                Text(label)
            }
            
            ForEach(1..<maximumRating + 1, id: \.self) { number in
                image(for: number)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 28, height: 28)
                    .foregroundColor(number > rating ? offColor : onColor)
                    .onTapGesture {
                        rating = number
                    }
            }
        }
    }
    
    func image(for number: Int) -> Image {
        if number > rating {
            return offImage ?? onImage
        } else {
            return onImage
        }
    }
}
明天介紹 @ViewBuilder,接續做 FeedBack 功能
下集待續