Search
Write a publication
Pull to refresh
15
0
Антон Грачёв @Tomcattoff

iOS

Send message

CocoaPods не предоставляет из коробки инструментов для повторного использования уже собранных артефактов между разными машинами разработчиков. Да и с локальным кэшированием существует ряд проблем.

Да, модули выкачиваются и сохраняются на диск, но они загружаются и подключаются к проекту в виде исходников. Это создаёт проблему, поскольку большое количество сторонних модулей, исходники которых практически никогда не требуется редактировать, замедляют индексацию и работу автокомплита в Xcode.

Конечно, из исходников модуля мы в итоге получаем бинарные артефакты при сборке. Но CocoaPods и сама система сборки Xcode не всегда корректно определяют набор модулей, которые необходимо пересобрать после изменений в коде проекта. В результате уже собранный модуль может пересобираться заново, а за ним — все зависимые от него модули также будут отправлены на пересборку. Простая очистка всего проекта приведет к тому же. А хотелось бы использовать уже собранные бинарные артефакты и не пересобирать исходники дважды, если они действительно не менялись.

В общем, я всё это к тому, что инструменты вроде Rugby, который мы упомянули в этом разделе, появились не просто так.

Нет, мы этого не делаем. Подключение подов к проекту выполняется через команду pod install, которую мы вызываем после генерации проекта. В Podfile указываются поды, которые нужно подключить к конкретному таргету проекта. Важно лишь следить за тем, чтобы имена таргетов в Project.swift для Tuist и в Podfile для CocoaPods совпадали.

Последние машины на Intel были выпущены в 2019 году. Apple обычно поддерживает свои продукты около 7 лет. Так что еще год-два скорее всего будут обновлять.

Я не специалист по хакинтошу, но предполагаю, что с большой долей вероятности потребуется яблочная железка.

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

Прошу прощения, ошибся веткой. Ответ вот тут.
C DependencyProvider ничего делать не нужно. Он будет зарегистрирован для конкретного контейнера во внутреннем регистре фабрик __DependencyProviderRegistry в сгенерированном коде.
У каждого контейнера, который наследуется от базового класса Component, есть следующий конструктор:
public init(parent: Scope) {
    self.parent = parent
    dependency = createDependencyProvider()
}

В методе createDependencyProvider() и происходит обращение к фабрике, которая создает DependecyProvider без каких-либо дополнительных действий со стороны разработчика:
private func createDependencyProvider() -> DependencyType {
    let provider = __DependencyProviderRegistry.instance.dependencyProvider(for: self)
    if let dependency = provider as? DependencyType {
        return dependency
    } else {
        // This case should never occur with properly generated Needle code.
        // Needle's official generator should guarantee the correctness.
        fatalError("Dependency provider factory for \(self) returned incorrect type. Should be of type \(String(describing: DependencyType.self)). Actual type is \(String(describing: dependency))")
    }
}

В RIBs у модуля может быть сущность Component, которая отвечает за зависимости модуля и помогает Builder-у в создании частей модуля. Вот этот компонент как раз может быть DI-контейнером Needle.
Не все проекты используют RIBs. Needle позволяет получить такое дерево контейнеров для любого архитектурного подхода (MVVM, MVC, etc).
Конечная цель генератора кода заключается в предоставлении DI-контейнеру зависимостей из других DI-контейнеров.
Допустим, что у нас есть такой контейнер:
protocol SomeUIDependency: Dependency {
    var router: Router { get }
}
final class SomeUIComponent: Component<SomeDependency> {
    var someObject: SomeObjectClass {
        shared {
            SomeObjectClass(router: dependecy.router)
        }
    }
}

router — это зависимость, которая предоставляется каким-то другим DI-контейнером. Пусть это будет RouterComponent.
Тогда генератор кода для SomeUIComponent создаст DependencyProvider, который может выглядеть следующим образом:
private class SomeUIComponent34170097de9901d91dcProvider: SomeUIDependency {
    var router: Router {
        return routerComponent.router
    }
    private let routerComponent: RouterComponent
    init(routerComponent: routerComponent) {
        self.rootComponent = routerComponent
    }
} 

Для связи между различными DependencyProvider и контейнерами генератор кода создает глобальную функцию registerProviderFactories(),
которую мы должны вызвать в своем коде до начала использования DI-контейнеров.
Внутри этой функции для рассмотренного SomeUIComponent будут находится следующие строки:
__DependencyProviderRegistry.instance.registerDependencyProviderFactory(for: "^->RootComponent->SomeUIComponent") { component in
        return SomeUIComponent34170097de9901d91dcProvider(component: component)
}

Если какая-то зависимость не находится, то генератор кода достаточно информативно оповещает об этом:
warning: Could not find a provider for (router: Router) which was required by SomeUIDependency, along the DI branch of ^->RootComponent->SomeUIComponent.
warning: Missing one or more dependencies at scope.
error: Some dependencies are missing, please look at the warnings above for the list.

Information

Rating
Does not participate
Location
Россия
Registered
Activity