Я пытаюсь создать легкую систему планирования задач.По сути, я могу обернуть некоторую асинхронную работу в Task
и отправить ее с TaskRunner
.В настоящее время бегун очень прост, просто вызывая start
на Task
и сохраняя его, чтобы он не был освобожден, пока он работает.Задача выглядит следующим образом:
enum TaskNotification<T> {
case start
case cancel
case complete(T)
case progress(TaskProgress)
}
typealias TaskNotificationHandler<TaskResponseType> = (TaskNotification<TaskResponseType>) -> Void
protocol Task: AnyObject {
associatedtype Response
var onChange: TaskNotificationHandler<Response> { get set }
func start()
func cancel()
}
Поэтому мне нравится тот факт, что я получаю строгую типизацию relatedType Response
.Однако, когда приходит время построить TaskRunner
, я получаю классическую ошибку компилятора "contains Self or AssociatedType requirements"
, поэтому я использую T: Task
, или я создаю стертую оболочку с типом AnyTask
.
class TaskRunner {
var currentTask: AnyTask<???>
func run<T: Task>(task: T) {
let boxed = AnyTask<???>(with: task)
currentTask = task
task.start()
}
}
Нодаже с стиранием типа (все еще неясно, что «стирается», а что не стирается), мне все равно нужно выбрать конкретный тип для универсального параметра <???>
.
В концея хочу создать конкретную реализацию Task
со строгой типизацией из связанного с протоколом типа, но позволить TaskRunner
управлять произвольными Task
, используя только те функции, которые ему нужны.(например, он не заботится о строго типизированном ответе)
Я просмотрел обобщения, стирание типов и даже использовал иерархию классов, но не нашел достойного решения.