爲什麼SwiftUI使用struct, 限制使用class

前言

在學習SwiftUI所有的地方,視圖元素都定義一個struct並實現View協議,該協議定義body變量返回View類型。
但是爲什麼,這裏一直是指定的struct, 而不是class呢?

嘗試使用class

如果你使用class 在SwiftUI中定義一個View,那麼你將遇到一個編譯器的錯誤

Protocol 'View' requirement '_makeView(view:inputs:)' cannot be satisfied by a non-final class ('ContentView') because it uses 'Self' in a non-parameter, non-result type position

錯誤的含義是,代碼中使用了ContentView作爲參數,如果ContentView有子類,那麼將產生未定義的行爲,必須限制ContentView沒有子類,因此需要加上final修飾

上面的錯誤和這裏類似:
https://stackoverflow.com/questions/40270118/protocol-requirement-cannot-be-satisfied-by-a-non-final-class-because-it-uses-s

加上final修飾之後,代碼可以編譯,運行之後直接崩潰:

SwiftUI/CustomView.swift:49: Fatal error: views must be value types (either a struct or an enum); ContentView is a class.
2022-02-23 15:41:34.418714+0800 SwiftClassUI[98636:8723744] SwiftUI/CustomView.swift:49: Fatal error: views must be value types (either a struct or an enum); ContentView is a class.


遇到斷言錯誤,這個是SwiftUI限制只能使用struct或者枚舉

爲什麼SwiftUI限制使用struct

經過搜索,大致有兩個地方說明原因:

  • 一個是stackoverflow上說,因爲SwiftUI中使用到了@State修飾狀態,將和state和當前view進行綁定,如果是class,會遇到問題
  • 而是2019年的wwdc, swiftui_essentials, 其中有一個點提到了SwiftUI爲什麼採用struct而不是像UIKit一樣的class

 If you're coming from UIKit or AppKitt, you've probably gotten used to views being defined as classes that inherit from a common view superclass instead of as structs conforming to protocols.
 For example, custom views in UIKit inherit from the UIView superclass.
 And UIView defines storage for common view properties like alpha and backgroundColor.
 Let's imagine we built our OrderHistory using UIKit instead of SwiftUI.
 Our Custom View would inherit the stored properties of UIView as well as adding more properties for its own custom behavior.
So how is SwiftUI different than this? Well, remember that in SwiftUI we represent those same kinds of common view properties as separate modifiers instead, like we did for opacity and background.
 And each of these modifiers creates their own view.
And this means that the storage for those properties is distributed across our view hierarchy in each of these modifier views instead of being inherited by every individual view.
Now this allows our views to be lighter weight, optimizing their storage for just their unique purpose.
And in this world, it makes a lot of sense that view just becomes a protocol because it's no longer needing to serve a common storage template for all of your views.
 But what does this view protocol actually do? Well, let's remember our conceptual definition of a view.
 Which is that a view defines a piece of our UI and we build bigger views by composing together smaller views.
 And that's all that the view protocol does.
 It defines a piece of our view hierarchy, giving it a name so that it can be composed and reused across your entire app.
 And each concrete type of view is just an encapsulation of some other view representing its contents in its body property and all of the inputs required to create that view represented by its properties.
Now the actual protocol just defines that one body property returning just another kind of view.
But look

總結

  • struct相比class,能節省更多空間,有時候不需要繼承父類中一些不需要的屬性
  • struct相比class,操作更快,struct在棧上分配空間更加快
  • struct符合SwiftUI中的設計思路,界面是簡單單一的,數據變化,UI就發生變化,數據不會在多處引用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章