VIPER デザイン パターンに従って、UIView アニメーション コードをどこに配置する必要がありますか?
ビューまたはプレゼンターにある必要がありますか?
ノート:
CustomView
タッチしたら画面上を移動したい があります。
が私のCustomView
画面に追加されますViewController
VIPER デザイン パターンに従って、UIView アニメーション コードをどこに配置する必要がありますか?
ビューまたはプレゼンターにある必要がありますか?
ノート:
CustomView
タッチしたら画面上を移動したい があります。
が私のCustomView
画面に追加されますViewController
[R]outer に配置する必要があります。この記事でよく説明されています:
プレゼンターにはユーザー入力に反応するロジックが含まれているため、いつ別の画面に移動するか、どの画面に移動するかを知っているのはプレゼンターです。一方、ワイヤーフレームはナビゲートする方法を知っています。そのため、プレゼンターはワイヤーフレームを使用してナビゲーションを実行します。一緒に、ある画面から次の画面へのルートを説明します。
ワイヤフレームは、ナビゲーション遷移アニメーションを処理する明らかな場所でもあります。
Router を Wireframe と呼んでいることに注意してください。
更新 (質問とコメントの更新に基づく回答の修正)
これらの 記事に基づいて意見を述べます。シンプルなケースとより洗練されたケースの 2 つを考えてみましょう。単純なケースでは、ビューの位置をアニメーションで定義済みの位置に変更するだけです (つまり、状態を変更します)。そしてより洗練されたケースでは、タスクはタッチの座標に基づいてカスタム ビューの位置を変更することです。
単純なケースを見てください。カスタム ビューを含む [View]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 によるビューの責任は、「ユーザーへの情報表示」と「ユーザー インタラクションの検出」であり、このイベントについて [P]resenter に通知することを除いて、タッチ後に何をすべきかを決定することは許可されていません。何をするか、何を呼ぶかの決定
[self.viperView changeCustomViewState];
したがって、[View]iew にあるアニメーションを実行する実際のコードですが、[P]resenter がその実行をトリガーします (その役割は、「ビューに何を表示するかを伝える」ことと「イベントを処理すること」であるため)。カスタム ビューの位置の定義は、ビューのレイアウトの一部です。したがって、それは構成の一部です。プレゼンターはそれをアニメーション化するだけです。
より洗練されたケースでは、タッチ位置に応じてカスタム ビューの位置を変更することを検討します。私たちの仕事は、画面上に残るように、タッチ後にビューの位置を変更することです。たとえば、ビューが画面の左下隅にある場合、タッチによってビューが画面の境界の下または画面の左側の後ろに移動してはなりません。3 つの空きコーナーのいずれかにビューを移動する必要があります。この場合、ビューのプロトコルは次のようになります。
@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]interactor を使用します。
// in Presenter class
[self.viperInteractor handleCoordinates:(CGPoint)point];
次に、[I]interactor は DataManager に [E]ntity のアルゴリズムを使用してこれらの座標を新しい座標にマップするように要求し (右上隅または左上隅に移動する必要があります)、[P]resenter に新しい座標 (隅のビュー) を通知します。移動する必要があります)。最後に、Presenter は以下を実行します。
[self.viperView changeCustomViewRelatedPosition:newPosition];
繰り返しますが、アニメーション コードはレイアウトの一部として [View]view 内に配置されます。ただし、決定(正確なパラメーター)は他のコンポーネント(Presenter、Interactor、Entity)によって定義されます
View (ViewController) に配置する必要があります。https://www.objc.io/issues/13-architecture/viper/ で内容を読むことができます。