SwiftUI笔记
@Published 标记对象定义的属性变更可以被监听,当对应字段变化时会触发对象 objectWillChange 通知,订阅了该属性的View也会收到值改变的通知
/// A type that publishes a property marked with an attribute. /// /// Publishing a property with the `@Published` attribute creates a publisher of this type. You access the publisher with the `$` operator, as shown here: /// /// class Weather { /// @Published var temperature: Double /// init(temperature: Double) { /// self.temperature = temperature /// } /// } /// /// let weather = Weather(temperature: 20) /// cancellable = weather.$temperature /// .sink() { /// print ("Temperature now: \($0)") /// } /// weather.temperature = 25 /// /// // Prints: /// // Temperature now: 20.0 /// // Temperature now: 25.0 ///
@ObservedObject 和 @State 类似,需要修饰的属性需要实现了 ObservableObject,@ObservedObject监听属性值的@Published属性变化会随属性修改则改变UI,@State是属性值自身发生变化时会影响UI呈现
class ObjectClass: ObservableObject { @Published var name: String @Published var source: Int init(name: String = "", source: Int = 0) { self.name = name self.source = source } } struct ContentView: View { @ObservedObject var data = ObjectClass() var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundColor(.accentColor) .onTapGesture { print("---> \(data.name)") data.name = "99999" } Text(data.name) SubView() .environmentObject(data) } .padding() } } struct SubView: View { @EnvironmentObject var data: ObjectClass var body: some View { TextField("输入框", text: $data.name) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
父View 以 @State 声明的属性 @State var param: DataType,可以在子View初始化的时候以 $param 给到子View,子View 通过 @Banding 关键字取得 param 数据关联,在值变化时进行相应的改变
var body: some View { HStack { Image(uiImage: UIImage(named: icon.isSelected ? "common_item_select" : "common_item_unselect")!) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 24.0~, height: 24.0~) Image(uiImage: icon.iconImage ?? UIImage()) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48.0~, height: 48.0~) Image(uiImage: UIImage(named: "edit_arrow")!) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 24.0~, height: 24.0~) ZStack { Image(uiImage: icon.originImage ?? UIImage()) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48.0~, height: 48.0~) Image(uiImage: UIImage(named: "edit_edit")!) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 16.0~, height: 16.0~) } HStack { Image(uiImage: UIImage(named: "edit_install")!) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 16.0~, height: 16.0~) Text("Install".localized) } // 属性配置是存在顺序依赖的,下一个配置是针对上一个返回,例如下面如果先设置高再设置内边距,则变成了再原有高度32.0基础上再增加内边距 .padding(EdgeInsets(top: 8.0~, leading: 8.0~, bottom: 8.0~, trailing: 8.0~)) .frame(height: 32.0~) .background(Color(PRUIUtils.sharedInstance().redColor)) .cornerRadius(15.0~) } }
控件元素没有铺满控件,这个时候点击子控件才会触发 onTapGesture 事件,但是如果设置上 background,那么在确定事件响应对象时,则会落到预期的控件上面去了,一定要记得设置背景(透明背景无效)
SwiftUI组件 设置了 id ,如果 id 为Builder中随机生成,那么可能将会触发view的不断重建