天天看點

SwiftUI直通車系列(4)—— 處理使用者互動

一、SwiftUI中的按鈕

   按鈕是處理使用者互動的最基礎的元件,在SwiftUI中,使用Button可以十分友善的定義按鈕元件,如下:

var count = 0

struct SimpleView:View {

   var body: some View {

       VStack(alignment: .center, spacing: 20) {

           Button(action:{

               count += 1

           }){

               Text("按鈕一")

           }

           Text("\(count)")

       }

   }

}

struct ContentView_Previews: PreviewProvider {

   static var previews: some View {

      SimpleView()

在預覽界面,可以看到一個按鈕和計數器已經布局在了頁面上,我們嘗試點選按鈕,會發現變量count雖然已經被改變了,但是頁面并沒有更新。能夠接收到使用者互動隻是第一步,在SwiftUI中通過使用者互動而進行頁面的重新整理才是核心我們需要關注的。效果如下:

SwiftUI直通車系列(4)—— 處理使用者互動

二、狀态

   SwiftUI采用的是描述性的結構化布局政策,即通過定義結構體這種結構化的資料來描述頁面的布局。這種布局思路開發直覺快速,并且非常易于入門上手。其與流行的前端架構Flutter,React等布局思路已經非常相似。是以,對于頁面的重新整理操作,我們也不能采用原始的iOS開發頁面重新整理的方式(對對象進行操作),而是要使用狀态來對元件進行管理,改變元件的狀态來實作元件重新整理操作。

   修改上面代碼如下:

   @State var count = 0

       VStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 20) {

               self.count += 1

           Text("\(self.count)")

重新恢複預覽,可以看到計數器的功能已經正常了。@State是SwiftUI中提供的一個屬性裝飾器,其可以将某個屬性指定為有狀态的,當有狀态的屬性發生變化時,與其綁定的元件會自動重新整理。

   如果有狀态屬性在父元件中,而我們需要在子元件中處理使用者互動邏輯進行頁面重新整理,這時,如果不做特殊的處理,子元件會因為結構體不可修改的原則而導緻無法對傳遞進來的狀态屬性進行更改。對于這種場景,我們可以使用SwiftUI中提供的@Binding裝飾器來修改子元件中的屬性,例如:

struct SimpleSubText:View {

   @Binding var count:Int

       Button(action:{

           self.count += 1

       }){

           Text("按鈕一")

       Text("\(self.count)")

           SimpleSubText(count: $count)

三、使用環境對象

   使用狀态來管理元件重新整理并不複雜,但是如果元件的嵌套層數較多,有狀态資料的傳遞可能需要層層下傳,這會使資料的流轉變得相對複雜。在SwiftUI中,還有另外一種方式,可以定義環境對象,環境對象在SwiftUI元件的任意位置都可以自由通路和修改,與環境對象有綁定關系的元件都會接收到變動的通知并重新整理。示例代碼如下:

// 作為環境資料的類,必須是可綁定監聽的,需要繼承ObservableObject

class EnviData: ObservableObject {

   @Published var count = 0

   // 擷取環境資料進行使用

   @EnvironmentObject var data:EnviData

           self.data.count += 1

       Text("\(self.data.count)")

           SimpleSubText()

       // 傳遞環境資料

       SimpleView().environmentObject(EnviData())

需要注意,并不是環境對象中所有的屬性都會觸發綁定和監聽,隻有使用@published的屬性才會觸發,是以環境對象也是支援靜态的内部屬性。