Swift в 2025 году: обзор новинок и практические примеры кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Swift в 2025 году: что нового на практике?

2025 год стал знаковым для экосистемы Apple. Вышел Swift 6 — релиз, который обещает не только стабильность, но и фундаментальные изменения в том, как мы пишем код. Если вы разработчик под iOS или macOS, вам необходимо разобраться в нововведениях, чтобы не отставать от индустрии. В этой статье мы разберём ключевые изменения Swift 6 на практических примерах, которые можно сразу применить в проектах.

1. Неисключающие перечисления (Non‑exhaustive enums)

Одно из самых ожидаемых изменений — возможность объявлять перечисления, которые могут расширяться в будущем без нарушения обратной совместимости. Раньше, если библиотека добавляла новый кейс в enum, ваш код ломался. Теперь это в прошлом.

Объявление такого перечисления выглядит так:

public enum NetworkError: Sendable {
    case timeout
    case serverError(Int)
    case unknown
    @_nonExhaustive case custom(String)
}

При обработке такого enum компилятор больше не требует, чтобы switch был исчерпывающим. Вы обязаны добавить default:

func handleError(_ error: NetworkError) {
    switch error {
    case .timeout:
        print("Тайм-аут")
    case .serverError(let code):
        print("Ошибка сервера: \(code)")
    default:
        print("Неизвестная ошибка")
    }
}

Практический совет: Если вы разрабатываете публичную библиотеку или SDK, помечайте свои enum атрибутом @_nonExhaustive — это сохранит совместимость с будущими версиями вашего кода.

2. Макросы: новый уровень метапрограммирования

Макросы, введённые в Swift 5.9, в 2025 году стали по-настоящему мощными. В Swift 6 появились макросы-атрибуты и макросы-члены, которые позволяют генерировать код на этапе компиляции без лишнего бойлерплейта.

Рассмотрим пример: вместо ручного написания init и Codable для модели, вы можете использовать встроенный макрос @MemberwiseInit (новинка Swift 6):

@MemberwiseInit
struct UserProfile: Codable {
    let id: Int
    var name: String
    var email: String
    var age: Int
}

// Компилятор автоматически генерирует:
// init(id: Int, name: String, email: String, age: Int)
// и реализацию Codable

Ещё один пример — макрос #Predicate для SwiftData:

let youngUsers = try modelContext.fetch(
    FetchDescriptor<UserProfile>(
        predicate: #Predicate { $0.age < 25 }
    )
)

Макросы значительно сокращают количество шаблонного кода и уменьшают вероятность ошибок. В 2025 году их использование стало стандартом для новых проектов.

3. Наблюдаемые свойства (Observable) и SwiftUI

В Swift 6 появился новый тип Observable, который пришёл на смену ObservableObject из Combine. Теперь не нужно писать @Published и @ObservedObject — всё работает через макрос @Observable.

Пример модели:

import Observation

@Observable
class CounterViewModel {
    var count = 0
    var isPremium = false

    func increment() {
        count += 1
        if count >= 10 {
            isPremium = true
        }
    }
}

Использование в SwiftUI стало проще:

struct CounterView: View {
    @State private var viewModel = CounterViewModel()

    var body: some View {
        VStack {
            Text("Счёт: \(viewModel.count)")
            Button("Увеличить") {
                viewModel.increment()
            }
            if viewModel.isPremium {
                Text("Премиум доступен!")
            }
        }
        .padding()
    }
}

Что изменилось?

  • Не нужно явно подписываться на изменения — SwiftUI сам отслеживает доступ к свойствам.
  • Улучшена производительность: обновляется только тот View, который читает изменившееся свойство.
  • Меньше кода: исчезли @Published, @ObservedObject и @StateObject (в новом синтаксисе).

4. Улучшенная параллельность и владение

Swift 6 вводит строгую проверку изоляции данных на уровне компилятора. Теперь Sendable проверяется жёстче, а неявное shared mutable state запрещено. Это делает многопоточный код безопасным без необходимости вручную расставлять блокировки.

Пример с async/await и акторами:

actor DataLoader {
    private var cache = [String: Data]()

    func loadData(from url: String) async throws -> Data {
        if let cached = cache[url] {
            return cached
        }
        let data = try await downloadData(from: url)
        cache[url] = data
        return data
    }

    private func downloadData(from url: String) async throws -> Data {
        let (data, _) = try await URLSession.shared.data(from: URL(string: url)!)
        return data
    }
}

// Использование
Task {
    let loader = DataLoader()
    let data = try await loader.loadData(from: "https://example.com/data.json")
    print("Данные получены: \(data.count) байт")
}

Ключевые нововведения:

  • Строгая Sendable-проверка: компилятор не даст передать не-Sendable тип между изолированными контекстами.
  • Улучшенные акторы: поддержка наследования и глобальных акторов.
  • Noncopyable типы: теперь можно создавать типы, которые нельзя копировать (полезно для управления ресурсами, например, файловыми дескрипторами).

Пример noncopyable типа:

struct FileDescriptor: ~Copyable {
    private let fd: Int32

    init(descriptor: Int32) {
        self.fd = descriptor
    }

    consuming func close() {
        Darwin.close(fd)
    }

    deinit {
        Darwin.close(fd)
    }
}

Такие типы гарантируют, что ресурс будет освобождён ровно один раз, предотвращая утечки и двойное закрытие.

Заключение

Swift 6 — это не просто очередное обновление, а ша

Блоги

Рекомендаций по книгам