Как стать автором
Обновить

Комментарии 5

Не хочу обидеть автора, но кажется, что проблема немного надуманная, а такое решение - это код ради кода, а не действительно что-то полезное. Причем решение крайне небезопасное и по сути не решающее проблему - оно никак не способствует обязательному вызову completion, и мы точно так же не заметим баг до того, пока не попадем в багованную ветку, только при этом вообще получим краш в рантайме.

Кажется, что можно решить проблему куда проще и безопаснее, например так:

class SomeService {
    func loadUser(completion: @escaping (Result<User, Error>) -> Void) {
        let result: Result<User, Error>
        defer { completion(result) }
        
        // make request and handle result
    }
}

Из минусов:

  • Приходится учитывать, что необходимо не вызывать completion самому, а использовать переменную result.

Из плюсов:

  • Не пишем никаких хитрых оберток, все очень понятно и прямолинейно.

  • Работает, наверное, вообще начиная со Swift 2 (если отбросить Result)

  • Самое главное: все проверки на этапе компиляции — если где-то ниже не присвоим result, то ошибка вылезет сразу. Это, кстати, сильно поможет с описанным выше минусом — если ты по привычке сделаешь completion(...); return, то компилятор сразу ругнется, что result не присвоен, и вероятно тут придется вспомнить, что вызов надо делать через переменную.

  • Никаких ограничений на @escaping и @nonescaping- подход работает где хочешь, делается в 2 строки.

Не знаю, реально ли автор пытался решать проблему, или это код чтобы потом сделать статью, но с учетом того, что оформлено оно в виде библиотеки на Github - даже не знаю, кто добровольно потащит себе такой костыль с fatalError'ами внутри ​

Как я понимаю Ваше решение только для синхронных функций подойдет.
Любой банальный async и работать не будет.

То что fatalError и его не стоит пихать туда - конечно, эт погорячились.
Но проблема такая существует.

> пока не попадем в багованную ветку
надо просто assert использовать и уже будет очень хорошо.
ну и можно написать тесты, если прям так хочется)

Вы зря фаталерроров боитесь. Это решение не отменяет ваше, а дополняет. Фаталеррор будет если кто-то применит Ваше решение неправильно. Если же правильно - то он никогда не сработает. То есть это последний рубеж обороны. Разбираться с двумя completion блоками или с невызванным блоком completion - то ещё сомнительное удовольствие - фаталеррор же во время QA сразу вылезет (ладно ладно может быть и не сразу). Впрочем тут про концепт. Впрочем всегда можно логирование ошибки вставить вместо фаталеррора - но тогда надо Void возвращать

НЛО прилетело и опубликовало эту надпись здесь

// упс, здесь мы забываем вызвать comletion(...)!

// упс, мы забыли поставить return

Ну так-то если забывать все подряд - никакие решения не помогут..
Можно еще забыть покрасить вьюшку в нужный цвет и начать пилить для этого решения

Зарегистрируйтесь на Хабре, чтобы оставить комментарий