根据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
已添加到屏幕中
答案 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/
中的内容