2016-01-27 5 views
3

Где должен быть размещен код анимации UIView в соответствии с шаблоном проектирования VIPER?Где разместить код анимации UIView в VIPER?

Должно ли это быть в представлении или в презентаторе?

Примечание:

У меня есть CustomView, что я хочу, чтобы перемещаться по экрану, как только прикоснулся.

CustomView добавляется к экрану в моем ViewController

+0

теги, которые вы использовали не являются для этого вопроса. Пожалуйста, просмотрите [Что такое теги и как их использовать?] (// stackoverflow.com/help/tagging) – SmokeDispenser

ответ

2

Вы должны поместить его в [R] внешнее. Это хорошо описано в this article:

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

Каркас также является очевидным местом для обработки перехода на посадку анимации.

Обратите внимание, что они называются Router как Wireframe.

Update (исправления ответа на основе обновлений вопроса и комментарии)

Я выскажу свое мнение, основанное на thesearticles. Давайте рассмотрим два случая: простые и более сложные. В простом случае задача состоит в том, чтобы просто изменить позицию представления на предопределенный с помощью анимации (т. Е. Изменить состояние). И в более сложном случае задачей является изменение позиции пользовательского представления на основе координат касания.

Взгляните на простой корпус. У вас есть [V] iewController, который содержит пользовательский вид. ViewController принимает протокол ViperView:

@protocol VIPERView 
- (void)changeCustomViewState; 
@end 

@interface ViewController : UIViewController<VIPERView> 
@end 

В реализации у нас есть что-то вроде этого:

@implementation ViewController { 
    BOOL _isInitialState; 
    IBOutlet UIView *_customView; 
} 

- (void)changeCustomViewState 
{ 
    _isInitialState = !_isInitialState; 
    [self changeCustomViewPositionAnimated:YES]; 
} 

- (void)changeCustomViewPositionAnimated:(BOOL)animated 
{ 
    void(^performChange)() = ^() { 
     if (_isInitialState) 
      _customView.center = CGPointMake(50, 50); 
     else 
      _customView.center = CGPointMake(250, 250); 
    }; 

    if (animated) 
    { 
     [UIView animateWithDuration:[CATransaction animationDuration] animations:^{ 
      performChange(); 
     }]; 
    } 
    else 
    { 
     performChange(); 
    } 
} 

В обязанности зрения в соответствии с VIPER является «отображение информации для пользователя» и «обнаружить взаимодействие с пользователем», и это ISN «т позволить принимать решения о том, что делать после того, как контакт, за исключением уведомления [P] resenter об этом событии. Presenter в свою очередь, принимает решение, что делать, и называет

[self.viperView changeCustomViewState]; 

Таким образом, фактический код, который выполняет анимацию, расположенную в [V] iew, но [P] resenter, запускает ее выполнение (поскольку его обязанности «сообщают, что отображать» и «Управлять событиями»). Определение позиции пользовательского представления - это часть макета представления. Так что это часть конфигурации. Презентатор просто превращает его в анимированный способ.

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

@protocol VIPERView 
// @param - related position to the screen bounds in range (0;1) 
- (void)changeCustomViewRelatedPosition:(CGPoint)point animated:(BOOL)animated; 
@end 

и в реализации

@implementation ViewController { 
    IBOutlet UIView *_customView; 
} 

- (void)changeCustomViewRelatedPosition:(CGPoint)point animated:(BOOL)animated 
{ 
    CGPoint thisCoordinateSpacePoint = // translate ‘point’ to screen’s coordinate space ; 
    void(^performChange)() = ^() { 
     _customView.center = thisCoordinateSpacePoint; 
    }; 

    if (animated) 
    { 
     [UIView animateWithDuration:[CATransaction animationDuration] animations:^{ 
      performChange(); 
     }]; 
    } 
    else 
    { 
     performChange(); 
    } 
} 

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 
{ 
    CGPoint point = //determine location 
    [self.viperPresenter userDidTouchViewWithPosition:point]; 
} 

@end 

Для [P] resenter нам необходимо определить протокол, в этом случае:

@protocol VIPERPresenter 
- (void)userDidTouchViewWithPosition:(CGPoint)point; 
@end 

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

[self.viperPresenter userDidTouchViewWithPosition:point]; 

В статье говорится:

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

В нашем случае приложение должно определять координаты, в которых следует перемещать представление. Этот алгоритм может быть инкапсулирован и взаимозаменяем. Таким образом, мы могли бы получить этот алгоритм из разных мест: базы данных, сервер и т.д. Для выполнения этой задачи мы используем [I] nteractor:

// in Presenter class 
[self.viperInteractor handleCoordinates:(CGPoint)point]; 

Тогда [I] nteractor просит DataManager, чтобы отобразить эти координаты на новые как-то с помощью алгоритм из [E] ntity (должен ли он перемещаться в верхнем правом или верхнем левом углу) и уведомляет обратно [P] resenter с новыми координатами (угол обзора должен перемещаться). И, наконец, Ведущий выполняет:

[self.viperView changeCustomViewRelatedPosition:newPosition]; 

Снова, код анимации размещен внутри [V] iew как часть макета. Но решение (точные параметры) определяются другими компонентами (Presenter, Interactor, Entity)

+0

Вопрос не в переходе между экранами. –

+0

Cheers @curious –

-1

Он должен быть помещен в View (ViewController) вы можете прочитать содержание в https://www.objc.io/issues/13-architecture/viper/

+0

Презентатор наследует от NSObject - вид наследует от UIViewController согласно https://github.com/mutualmobile/VIPER-TODO –

+0

@ Ríomhaire Посмотрите на эту группу файлов. Они используются Wireframe (Presenter), и внутри них выполняются анимации UIVIew. Я согласен, что этот пример не дает прямого ответа на ваш вопрос, но вы слишком строги. – curious

+0

Что вы подразумеваете под «Они используются Wireframe (Presenter)». Wireframe и Presenter - это совершенно разные вещи. Возможно, вы имели в виду "Wireframe (Router)"? –