VIPER 中的 UIView 动画代码放在哪里?
Where to place UIView animation code in VIPER?
按照VIPER设计模式,UIView动画代码应该放在哪里?
它应该在 View 中还是在 Presenter 中?
注:
我有一个 CustomView
,我希望在触摸后在屏幕上移动。
CustomView
已添加到我的 ViewController
中的屏幕
你应该把它放在[R]外面。在 this article:
中有详细描述
Since the Presenter contains the logic to react to user inputs, it is
the Presenter that knows when to navigate to another screen, and which
screen to navigate to. Meanwhile, the wireframe knows how to navigate.
So, the Presenter will use the wireframe to perform the navigation.
Together, they describe a route from one screen to the next.
The wireframe is also an obvious place to handle navigation transition
animations.
请注意,他们将路由器称为线框。
更新(根据问题和评论的更新回答更正)
我会根据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,视图的职责是 "display information to the user" 和“检测用户交互”,并且不允许决定触摸后要做什么,除非通知 [P]resenter 有关此事件。Presenter in轮到它决定做什么和打电话
[self.viperView changeCustomViewState];
因此执行动画的实际代码位于 [V]iew 但 [P]resenter 触发它的执行(因为它的职责是 "tell the view what to display" 和 "Handle events")。
定义自定义视图的位置只是视图布局的一部分。所以它是配置的一部分。 Presenter只是以动画的方式转动它。
在更复杂的情况下,我们会考虑根据触摸位置更改自定义视图的位置。
我们的任务是在触摸后改变视图的位置,使其保持在屏幕上。例如,如果视图位于屏幕的左下角,则触摸不应将其移动到屏幕边界以下或屏幕左侧后面。它应该将视图移动到三个自由角之一。
在这种情况下,我们的视图协议将如下所示:
@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];
如文章所述:
The presenter is notified of events by the view and part of its job is
to handle those events accordingly. This usually means asking the
interactor to retrieve some bit of information or carry out some task.
在我们的案例中,应用程序需要确定应移动视图的坐标。该算法可以封装并且可以互换。所以我们可以从不同的地方检索这个算法:数据库、服务器等。为了完成这个任务,我们使用 [I]nteractor:
// in Presenter class
[self.viperInteractor handleCoordinates:(CGPoint)point];
然后 [I]nteractor 要求 DataManager 使用来自 [E]ntity 的算法以某种方式将这些坐标映射到新的坐标(它应该移动到右上角还是左上角)并用新的通知回 [P]resenter坐标(角视图应该移动)。最后 Presenter 执行:
[self.viperView changeCustomViewRelatedPosition:newPosition];
同样,动画代码作为布局的一部分放在 [V]view 中。但决策(确切参数)由其他组件(Presenter、Interactor、Entity)定义
应该放在视图中(ViewController)
您可以阅读https://www.objc.io/issues/13-architecture/viper/
中的内容
按照VIPER设计模式,UIView动画代码应该放在哪里?
它应该在 View 中还是在 Presenter 中?
注:
我有一个 CustomView
,我希望在触摸后在屏幕上移动。
CustomView
已添加到我的 ViewController
你应该把它放在[R]外面。在 this article:
中有详细描述Since the Presenter contains the logic to react to user inputs, it is the Presenter that knows when to navigate to another screen, and which screen to navigate to. Meanwhile, the wireframe knows how to navigate. So, the Presenter will use the wireframe to perform the navigation. Together, they describe a route from one screen to the next.
The wireframe is also an obvious place to handle navigation transition animations.
请注意,他们将路由器称为线框。
更新(根据问题和评论的更新回答更正)
我会根据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,视图的职责是 "display information to the user" 和“检测用户交互”,并且不允许决定触摸后要做什么,除非通知 [P]resenter 有关此事件。Presenter in轮到它决定做什么和打电话
[self.viperView changeCustomViewState];
因此执行动画的实际代码位于 [V]iew 但 [P]resenter 触发它的执行(因为它的职责是 "tell the view what to display" 和 "Handle events")。 定义自定义视图的位置只是视图布局的一部分。所以它是配置的一部分。 Presenter只是以动画的方式转动它。
在更复杂的情况下,我们会考虑根据触摸位置更改自定义视图的位置。 我们的任务是在触摸后改变视图的位置,使其保持在屏幕上。例如,如果视图位于屏幕的左下角,则触摸不应将其移动到屏幕边界以下或屏幕左侧后面。它应该将视图移动到三个自由角之一。 在这种情况下,我们的视图协议将如下所示:
@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];
如文章所述:
The presenter is notified of events by the view and part of its job is to handle those events accordingly. This usually means asking the interactor to retrieve some bit of information or carry out some task.
在我们的案例中,应用程序需要确定应移动视图的坐标。该算法可以封装并且可以互换。所以我们可以从不同的地方检索这个算法:数据库、服务器等。为了完成这个任务,我们使用 [I]nteractor:
// in Presenter class
[self.viperInteractor handleCoordinates:(CGPoint)point];
然后 [I]nteractor 要求 DataManager 使用来自 [E]ntity 的算法以某种方式将这些坐标映射到新的坐标(它应该移动到右上角还是左上角)并用新的通知回 [P]resenter坐标(角视图应该移动)。最后 Presenter 执行:
[self.viperView changeCustomViewRelatedPosition:newPosition];
同样,动画代码作为布局的一部分放在 [V]view 中。但决策(确切参数)由其他组件(Presenter、Interactor、Entity)定义
应该放在视图中(ViewController) 您可以阅读https://www.objc.io/issues/13-architecture/viper/
中的内容