2014-10-23 2 views
2

Когда мое приложение запускается, я извлекаю удаленный файл конфигурации, содержащий информацию (URL-адреса и т. Д.), Необходимые для настройки других зависимостей.Typhoon - Runtime Настраиваемые компоненты с помощью раскадровки

После получения удаленной конфигурации у меня есть объект Config, который мне нужно передать другим TyphoonDefinition.

Теперь я также использую интеграцию плагинов plist.

Я изначально шел по пути ввода сборки в ViewController, который загружает объект Config, и когда я получаю удаленный конфиг и создаю объект Config, я бы как-то установил его как свойство на сборке. Я сделал это в надежде, что я мог бы использовать свойство в определениях, но это не сработало, и я получил:

2014-10-22 21:18:06.203 four[39840:516543] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'No component matching id 'setConfig:'.' 
*** First throw call stack: 
(
    0 CoreFoundation      0x000000010a3e63f5 __exceptionPreprocess + 165 
    1 libobjc.A.dylib      0x000000010a07fbb7 objc_exception_throw + 45 
    2 CoreFoundation      0x000000010a3e632d +[NSException raise:format:] + 205 
    3 four        0x00000001070a011d -[TyphoonComponentFactory componentForKey:args:] + 148 
    4 CoreFoundation      0x000000010a2de22c __invoking___ + 140 
    5 CoreFoundation      0x000000010a2de082 -[NSInvocation invoke] + 290 
    6 CoreFoundation      0x000000010a36d456 -[NSInvocation invokeWithTarget:] + 54 
    7 four        0x000000010709d358 -[TyphoonBlockComponentFactory forwardInvocation:] + 276 

Есть ли способ для меня, чтобы ввести объект в сборку во время выполнения?

Есть ли более чистый способ делать то, что я пытаюсь сделать?

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

Например, у меня это определение. Мне нужно передать объект конфигурации времени выполнения в качестве параметра конструктору.

- (id<ApiService>)apiService 
{ 
    return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) {}]; 
} 

ответ

2

Используя аргументы во время выполнения

К примеру, у меня есть это как определение. Мне нужно передать runtime объект Config в качестве параметра для конструктора.

- (id<ApiService>)apiService { 
return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) {}]; } 

Попробуйте что-то вроде этого:

- (id<ApiService>)apiServiceWithConfig:(Config *)config { 
    return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) { 

     // inject into property: 
     [definition injectProperty:@selector(config) with:config]; 

     // inject into constructor: 
     [definition useInitializer:@selector(initWithConfig:) parameters:^(TyphoonMethod *initializer) { 
      [initializer injectParameterWith:config]; 
     }]; 

    }]; 
} 

Используя определение фабрики

Взгляните на следующие два определения:

- (Config *)currentConfig { 
    return [TyphoonDefinition withFactory:[self configManager] selector:@selector(currentConfig)]; 
} 

- (ConfigManager *)configManager { 
    return [TyphoonDefinition withClass:[ConfigManager class] configuration:^(TyphoonDefinition *definition){ 
     definition.scope = TyphoonScopeSingleton; 
    }]; 
} 

Представьте, что вы есть ConfigM anager, который загружает удаленный конфиг и сохраняет его как свойство currentConfig, определение «configManager» описывает этот объект.

Затем проверьте определение 'currentConfig'. Это определение просто возвращает результат вызова метода currentConfig в экземпляре ConfigManager.

Затем вы можете придать конфигурации, как:

- (id<ApiService>)apiService { 
    return [TyphoonDefinition withClass:[ApiService class] configuration:^(TyphoonDefinition* definition) { 
     [definition injectProperty:@selector(config) with:[self currentConfig]]; 
    }]; 
} 

Но убедитесь, что currentConfig загружен (не ноль) при создании 'apiService'. (возможно, лучше ввести ConfigManager вместо этого - тогда, если currentConfig nil, он будет заполнен позже)

+0

Спасибо за ответ. Я предполагаю, что я не совсем понимаю аргументы времени исполнения, так как вы предоставляете аргумент. Я вставляю сборку, а затем вызываю метод для ввода аргумента? Кроме того, вам нужно только вызвать его один раз, а затем все инъекции после этого будут содержать обновленную зависимость? – Steve

+0

Это решение не использует аргументы времени исполнения. Он использует так называемый заводский компонент. Нажмите ссылку на темы в файле Readme этого приложения для тайфуна: https://github.com/typhoon-framework/Typhoon-example –

+0

https://github.com/typhoon-framework/Typhoon-example/blob/master/PocketForecast /Assembly/PFThemeAssembly.m –

1

Несколько моментов:

  • время выполнения аргументы супер-крутая особенность и действительно помогают получить полную силу тайфуна. Мы настоятельно рекомендуем узнать о них (задавайте вопросы здесь, если хотите). Они не подходят для того, что вы пытаетесь сделать, хотя.
  • Можно зарегистрировать новое определение в контейнере во время выполнения с помощью:

.

- (void)registerDefinition:(TyphoonDefinition *)definition; 

. , вы, вероятно, тоже не хотите делать это в своем случае.


что вы являются интересует:

TyphoonComponentFactoryPostProcessor и TyphoonComponentPostProcessor:

Typhoon имеет два вида интерфейсов, которые могут быть присоединены, один TyphoonComponentFactoryPostProcessor, а другой TyphoonComponentPostProcessor. Они используются внутри, но вы также можете писать свои собственные и делать с ними всевозможные интересные вещи.

  • TyphoonComponentFactoryPostProcessor: Изменяет определений (рецепты) для компонента, прежде чем он будет построен.

  • TyphoonComponentPostProcessor: Изменяет экземпляры после того, как они построены.


TyphoonConfig:

Существует существующий TyphoonComponentFactoryPostProcessor, который можно использовать для выполнения этой задачи, которую вы описали. Его называют TyphoonConfigPostProcessor и составляет described in the user guide here.

Всех почтовых процессоров может быть прикреплен либо на встроенное время (в сборке), или во время выполнения, а именно:

TyphoonConfigPostProcessor* configurer = [[TyphoonConfigPostProcessor alloc] init]; 
[configurer useResourceWithName:@"Configuration.plist"]]; 
[factory attachPostProcessor:configurer]; 


Обратите внимание, что, поскольку TyphoonComponentFactoryPostProcessor изменяет определения, если у вас есть компоненты Singleton scope, которые уже построены, они не будут затронуты. Вам придется либо создавать ленивые одиночные игры, либо звонить по телефону [factory unload].


Как получить ссылку на TyphoonComponentFactory после запуска?

Что бы ни делало в вашем приложении шаг настройки, необходимо сделать «Тайфун Aware». Вы можете сделать это, используя следующее:

- (ConfigController *)configController 
{ 
    return [ConfigController withClass:[INFGiftDeliveryAddressController class] 
     configuration:^(TyphoonDefinition *definition) 
    {   
     [definition injectProperty:@selector(factory) with:self]; 
    }]; 

. , при вводе сборки вы можете объявить свойство типа TyphoonComponentFactory или любой из ваших подклассов сборки. Он будет работать в любом случае. Документация по этой функции is here.

В мобильных и настольных приложениях ваши компоненты часто должны быть сделаны «Typhoon aware», поэтому мы можем перейти от одного графа объектов (например, к контроллеру представления) к другому (и это то, где функции аргументов во время выполнения может быть полезна). Обратите внимание, что вы кодируете свой собственный интерфейс для конкретного домена, поэтому Typhoon является «неинвазивным». По большей части ваши приложения напрямую не ссылаются на какие-либо API-интерфейсы Typhoon.

Мы здесь довольно много рассмотрели, поэтому, если у вас есть какие-либо дополнительные вопросы или вы нуждаетесь в разъяснениях, не стесняйтесь спрашивать.

+0

Благодарим вас за помощь в понимании. Здесь много вариантов, и я не уверен, что полностью понимаю лучший подход. Теперь, в моем случае, я извлекаю удаленный конфиг, поэтому мне придется дождаться завершения операции async-сети, прежде чем у меня появится объект. В примере TyphoonConfigPostProcessor вы ссылаетесь на файл plist ... По-моему, мне трудно найти связь с тем, как я буду использовать это в своем случае. Кроме того, почему аргументы времени исполнения не подходят? – Steve

+0

Вы правы, я дал вам много информации (возможно, слишком много), но как только вы поймете основные функции, легко их собрать и создать свои собственные решения. Тем не менее, это информация о стоимости книги, поэтому давайте сначала сосредоточимся на вашей конкретной проблеме и пойдем с подходом Алексея. Что касается двух других вопросов: а) Что такое аргументы времени исполнения? Можете ли вы опубликовать отдельный вопрос? б) Что такое функция TyphoonConfig и почему она использует plist? Можете ли вы также задать отдельный вопрос? –

Смежные вопросы