Если вы уже какое-то время разрабатываете приложения на SwiftUI, вы, вероятно, испытывали раздражение, когда одни и те же строки кода проникают в каждый проект. SwiftUI — мощный инструмент, да, но иногда он заставляет писать всё снова и снова: настраивать модификаторы, обрабатывать ошибки, управлять опциональными параметрами, форматировать даты.
В чём секрет? Вам не нужно мириться с повторениями. С помощью нескольких умных расширений и шаблонов вы можете сделать код SwiftUI чище, короче и при этом таким же мощным. Вот десять небольших трюков, которые незаметно избавят вас от ненужных элементов, придав коду вашего приложения элегантный вид.
1. Более безопасный способ развертывания Optional в представлениях
Вместо бесконечных операторов if let создайте простое расширение, которое сделает обработку опциональных параметров естественной:
extension View {
@ViewBuilder
func ifLet<T, Content: View>(_ value: T?, content: (T) -> Content) -> some View {
if let value {
content(value)
} else {
self
}
}
}
Теперь вы можете просто писать:
Text("Hello")
.ifLet(username) { Text("Welcome, \($0)") }
2. Условные модификаторы без лишних сложностей
Мы все пишем .padding() или .opacity() с условиями. Вместо того, чтобы заключать целые представления в блоки if, используйте это:
extension View {
@ViewBuilder
func apply(_ condition: Bool, modifier: (Self) -> some View) -> some View {
if condition {
modifier(self)
} else {
self
}
}
}
Использование:
Text("Premium")
.apply(isPro) { $0.foregroundColor(.yellow) }
дна строка, ничего лишнего.
3. Многоразовый AsyncImage с плейсхолдером
Загрузка изображений — обычное дело, но повторение одной и той же логики плейсхолдера утомляет. Сделайте один раз:
struct RemoteImage: View {
let url: URL
var body: some View {
AsyncImage(url: url) { phase in
switch phase {
case .success(let image): image.resizable().scaledToFit()
case .failure(_): Color.gray
case .empty: ProgressView()
@unknown default: EmptyView()
}
}
}
}
Теперь вам больше не придётся переписывать загрузчики изображений.
4. Форматирование даты в одну строку
Вместо того, чтобы создавать DateFormatter везде, добавьте расширение:
extension Date {
func formatted(_ style: DateFormatter.Style = .medium) -> String {
let formatter = DateFormatter()
formatter.dateStyle = style
return formatter.string(from: self)
}
}
Использование:
Text(Date().formatted(.long))
Легко читаемый и многоразовый код.
5. Автоматические вставки SafeArea
Не любите бороться с .ignoresSafeArea()? Добавьте небольшой вспомогательный метод:
extension View {
func fillScreen() -> some View {
self.frame(maxWidth: .infinity, maxHeight: .infinity)
.ignoresSafeArea()
}
}
Теперь для каждого полноэкранного представления требуется всего один модификатор.
6. Простая навигация без шаблонных NavigationLinks
Вместо того, чтобы разбрасывать NavigationLinks по всему коду, вы можете упростить навигацию с помощью вспомогательного метода:
extension View {
func navigate<Destination: View>(to destination: Destination, when binding: Binding<Bool>) -> some View {
background(
NavigationLink(destination: destination, isActive: binding) { EmptyView() }
)
}
}
Использование:
Button("Go") { showDetails = true }
.navigate(to: DetailView(), when: $showDetails)
Внезапно навигация снова кажется понятной.
7. Многоразовые разделители
Вместо того, чтобы вводить .frame(height: 20) для задания отступа, создайте ощущение, будто SwiftUI сам предоставил вам этот инструмент:
struct Gap: View {
let height: CGFloat
var body: some View { Spacer().frame(height: height) }
}
Использование:
VStack {
Text("Title")
Gap(height: 16)
Text("Subtitle")
}
Более чистый и семантический код.
8. Унифицированная обработка алертов
Надоело писать оповещения снова и снова? Централизуйте их:
struct AlertItem: Identifiable {
var id = UUID()
var title: String
var message: String
}
extension View {
func alert(item: Binding<AlertItem?>) -> some View {
self.alert(item.wrappedValue?.title ?? "",
isPresented: Binding(value: item.isNotNil())) {
} message: {
Text(item.wrappedValue?.message ?? "")
}
}
}
Теперь отображение предупреждений выглядит так:
.alert(item: $errorItem)
9. Быстрые помощники предварительного просмотра
Избавьтесь от повторения тестовых данных в предпросмотрах. Добавьте помощников:
extension PreviewProvider {
static var sampleUser: User { User(id: 1, name: "Alice") }
}
Затем в ваших превью:
ContentView(user: sampleUser)
Больше никаких лишних данных.
10. Однострочное представление загрузки
Вместо того, чтобы каждый раз переписывать состояния загрузки, запрограммируйте их:
extension View {
func loading(_ isLoading: Bool) -> some View {
ZStack {
self
if isLoading {
ProgressView().scaleEffect(1.5)
}
}
}
}
Использование:
List(items) { item in
Text(item.title)
}
.loading(isFetching)
Каждое представление теперь поддерживает состояние загрузки.
Подведение итогов
SwiftUI даёт вам свободу, но вместе со свободой приходит и повторение. Создавая собственные небольшие строительные блоки — расширения, вспомогательные функции и шаблоны — вы не только экономите время, но и создаёте персональный инструментарий SwiftUI, который растёт с каждым проектом.
Меньше кода. Та же мощь. Больше удовольствия. Вот как должен выглядеть SwiftUI.

