some View и AnyView в SwiftUI. Тема не новая, но споры о правильном использовании периодически возвращаются.Коротко:
some View сохраняет конкретный тип View на этапе компиляции.AnyView стирает тип и оставляет только «какой-то View» на этапе выполнения.Когда мы пишем:
var body: some View {
Text("Cowabunga")
}Мы говорим компилятору:
тип конкретный и известен, но имя типа скрыто.
SwiftUI при этом:
- строит статическое дерево типов
- может оптимизировать diff
- лучше отслеживает identity View
- эффективнее обновляет UI
А с
AnyView:AnyView(Text("Cowabunga"))Мы теряем информацию о реальном типе и часть работы переносится в runtime.
SwiftUI больше не знает:
- какая структура View внутри
- как оптимизировать обновления
🍕 Классический пример
func content(isLoggedIn: Bool) -> some View {
if isLoggedIn {
return HomeView()
} else {
return LoginView()
}
}Компилятор ругается, потому что возвращаются разные типы.
Можно быстро пофиксить так:
func content(isLoggedIn: Bool) -> AnyView {
if isLoggedIn {
return AnyView(HomeView())
} else {
return AnyView(LoginView())
}
}Работает, но ухудшает оптимизации SwiftUI, да и ревью вряд ли пройдет.
😅 Нормальный SwiftUI-подход - использовать
ViewBuilder.@ViewBuilder
func content(isLoggedIn: Bool) -> some View {
if isLoggedIn {
HomeView()
} else {
LoginView()
}
}
SwiftUI создаёт:
ConditionalContent<HomeView, LoginView>
И сохраняет типовую информацию для оптимизаций.
Когда
AnyView действительно нужен:- массив разных View
- runtime injection View
- API, где нельзя использовать generics
Например:
let cells: [AnyView] = [
AnyView(ProfileHeaderView()),
AnyView(SettingsRow(...))
]
🍕 Можно сформулировать простое правило:
Если SwiftUI может знать тип на этапе компиляции → используем
some View.Если тип появляется только во время выполнения → используем
AnyView.AnyView не зло, но его легко начать использовать как костыль. Поэтому имеет смысл ограничивать использование или подсвечивать его линтером.#R #SwiftUI #Performance #Architecture
👏
