0Pricing
Swift Academy · Урок

Планировщики и потоки выполнения

Управляйте выполнением с помощью receive(on:) и subscribe(on:).

«Планировщики и потоки выполнения» — бесплатный урок Swift Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.

Планировщики в Combine

Планировщик в Combine определяет, когда и где выполняется работа: какой поток или очередь запускает операторы и доставляет значения подписчикам.

Управление планировщиками необходимо, чтобы обновления пользовательского интерфейса выполнялись в главном потоке, а тяжёлая работа — за его пределами.

Два ключевых оператора

Combine предоставляет два оператора для управления потоками выполнения:

  • subscribe(on:) — определяет, где начинается подписка и работа upstream
  • receive(on:) — определяет, где доставляются значения downstream

Они управляют разными концами конвейера.

receive(on:)

receive(on:) перемещает всё, что идёт после него, на указанный планировщик. Чаще всего его используют, чтобы вернуться в главную очередь перед обновлением пользовательского интерфейса.

apiClient.fetchUser(id: 1)
    .receive(on: DispatchQueue.main)
    .sink { user in
        self.nameLabel.text = user.name
    }
    .store(in: &cancellables)

subscribe(on:)

subscribe(on:) определяет поток выполнения, в котором publisher начинает выдавать значения, а также поток для работы операторов upstream. Используйте его, чтобы перенести дорогостоящую настройку из главного потока.

heavyPublisher
    .subscribe(on: DispatchQueue.global(qos: .userInitiated))
    .receive(on: DispatchQueue.main)
    .sink { result in
        self.update(result)
    }
    .store(in: &cancellables)

subscribe(on:) и receive(on:)

Запомните направление:

  • subscribe(on:) влияет на upstream — место, где начинается работа
  • receive(on:) влияет на downstream — место доставки результатов

Обычно subscribe(on:) используют для фоновой работы, а receive(on:) — для доставки в главный поток.

DispatchQueue как планировщик

DispatchQueue соответствует протоколу Scheduler. DispatchQueue.main доставляет значения в главный поток, а очереди global выполняют работу параллельно в background.

let background = DispatchQueue.global(qos: .background)

publisher
    .map { expensiveTransform($0) }
    .subscribe(on: background)
    .receive(on: DispatchQueue.main)
    .sink { self.render($0) }
    .store(in: &cancellables)

RunLoop как планировщик

RunLoop — ещё один планировщик, связанный с циклом обработки событий потока. RunLoop.main доставляет значения в координации с событиями пользовательского интерфейса, что может быть важно, например, для плавности прокрутки.

timerPublisher
    .receive(on: RunLoop.main)
    .sink { _ in
        self.tick()
    }
    .store(in: &cancellables)

DispatchQueue и RunLoop

Оба планировщика могут доставлять значения в главный поток, но между ними есть тонкие различия:

  • DispatchQueue.main — планирует работу даже во время отслеживания прокрутки
  • RunLoop.main — откладывает работу, пока цикл обработки событий находится в режиме отслеживания

Для большинства обновлений пользовательского интерфейса после асинхронной работы безопаснее использовать DispatchQueue.main по умолчанию.

Операторы времени планировщика

Такие операторы, как debounce, throttle и delay, принимают аргумент-планировщик, который определяет, какая очередь отвечает за отсчёт времени.

searchTextPublisher
    .debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
    .sink { query in
        self.runSearch(query)
    }
    .store(in: &cancellables)

Распространённая ошибка при работе с потоками

Обновление пользовательского интерфейса не в главном потоке приводит к сбоям или визуальным дефектам. Если после publisher, работающего в background, забыть добавить receive(on: DispatchQueue.main), Ваш sink может выполняться в фоновом потоке.

Всегда доставляйте значения, предназначенные для пользовательского интерфейса, через главный планировщик.

Собираем всё вместе

Надёжный конвейер запускает работу в background, обрабатывает данные там, а затем доставляет результат в главный поток для отображения.

imageURLPublisher
    .subscribe(on: DispatchQueue.global())
    .flatMap { url in downloadImage(url) }
    .map { resize($0) }
    .receive(on: DispatchQueue.main)
    .sink { self.imageView.image = $0 }
    .store(in: &cancellables)

Быстрая проверка

Проверьте свои знания о планировщиках.

Итоги

Вы научились управлять потоками выполнения в Combine:

  • subscribe(on:) — место начала работы upstream
  • receive(on:) — место доставки результатов
  • DispatchQueue и RunLoop в роли планировщиков
  • Всегда доставляйте обновления пользовательского интерфейса в главный поток

Правильное планирование сохраняет отзывчивость приложений и предотвращает сбои.

Часто задаваемые вопросы

Урок «Планировщики и потоки выполнения» бесплатный?

Да — полный текст урока «Планировщики и потоки выполнения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.

Чему я научусь в уроке «Планировщики и потоки выполнения»?

Управляйте выполнением с помощью receive(on:) и subscribe(on:). Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Swift Academy?

Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Планировщики и потоки выполнения»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Swift Academy?

Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Преобразование и объединение потоков
  2. Планировщики и потоки выполнения
  3. Операторы обработки ошибок
  4. Пользовательские издатели и подписчики
← Назад к Swift Academy