在VIPER中放置UIView动画代码的位置?

时间:2016-01-27 14:49:20

标签: ios objective-c architecture viper-architecture

根据VIPER设计模式放置UIView动画代码在哪里?

它应该在视图中还是在演示者中?

注意:

我有一个app.directive("testDir", function() { var directive = { restrict: "A", template: "<div><input value='TestButton' type='button' data-ng-disabled='IsDisabled'></div>", scope: { IsDisabled: "=isDisabled" } }; return directive; }); ,我想在触摸屏幕后移动屏幕。

CustomView

中的CustomView已添加到屏幕中

2 个答案:

答案 0 :(得分:2)

你应该把它放在[R]外面。它在this article

中有详细描述
  

由于Presenter包含对用户输入作出反应的逻辑,因此它是   知道何时导航到另一个屏幕的Presenter,以及哪个   屏幕导航到。同时,线框知道如何导航。   因此,Presenter将使用线框来执行导航。   他们一起描述了从一个屏幕到下一个屏幕的路线。

     

线框也是处理导航过渡的明显位置   动画。

请注意,他们将路由器称为线框。

更新(根据问题和评论的更新回答更正)

我会根据these articles发表意见。 让我们考虑两种情况:简单和复杂。在简单的情况下,任务只是将视图的位置改变为具有动画的预定义位置(即改变状态)。在更复杂的情况下,任务是根据触摸坐标改变自定义视图的位置。

看看简单的案例。你有一个包含自定义视图的[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的观点责任是&#34;向用户显示信息&#34;并且&#34;检测用户交互“并且除了通知[P] resenter关于此事件之外,不允许在触摸之后做出决定该做什么。演示者轮流决定做什么和打电话

[self.viperView  changeCustomViewState];

因此,执行位于[V] iew但[P] resenter的动画的实际代码会触发其执行(因为它的职责是&#34;告诉视图显示什么&#34;以及&#34;处理事件&#34; )。 定义自定义视图的位置是视图布局的jsut部分。所以它是配置的一部分。演示者只需以动画方式转动它。

在更复杂的情况下,我们会考虑根据触摸位置更改自定义视图的位置。 我们的任务是在触摸后改变视图的位置,使其保持在屏幕上。例如,如果视图位于屏幕的左下角,则触摸不应将其移动到屏幕边界下方或屏幕左侧后面。它应该在三个自由角之一中移动视图。 在这种情况下,我们的视图协议将如下所示:

@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];

正如文章所述:

  

演示者会通过视图通知事件,部分工作是   相应地处理这些事件。这通常意味着要求   交互者检索一些信息或执行某些任务。

在我们的案例中,app需要确定应该移动视图的坐标。该算法可以封装并且可以互换。所以我们可以从不同的地方检索这个算法:数据库,服务器等。为了完成这个任务,我们使用[I] nteractor:

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

然后[I] nteractor要求DataManager使用[E]中的算法(如果它在右上角或左上角移动)以某种方式将这些坐标映射到新的坐标,并用新坐标通知[P] resenter(角落视图应该移动)。最后,Presenter执行:

[self.viperView changeCustomViewRelatedPosition:newPosition];

同样,动画代码作为布局的一部分放在[V]内。但决定(确切参数)由其他组件(Presenter,Interactor,Entity)定义

答案 1 :(得分:-1)

它应放在View(ViewController)中 您可以阅读https://www.objc.io/issues/13-architecture/viper/

中的内容