アップデート成功の秘of:インターフェース、バックエンド、アプリケーション構造

待望の年末年始が近づいています-旅行時間。 この点で、本日はTravel And Play- Webcam World Viewとの共同プロジェクトでの作業についてお話したいと思います 。 このアプリケーションにより、世界中のさまざまな場所に設置されたビデオカメラからのストリームに接続し、リアルタイムで沸騰する生活を見ることができます。



いいですね そのように思えたのは、この秋までに、タスクは製品の新しい改善されたバージョンのために設定されました。 正確に改善することは私たちの裁量にあったので、すぐに機能をそのままにしておくことに決めました。それは非常に十分であり、同時に過負荷になりません。 しかし、UXコンポーネントと技術的なパフォーマンスは大幅に改訂されました。 最初は良いアプリケーションからキャンディを作った方法については、以下をお読みください。









まず、私たちは現状を分析しました。 判明したように、アプリケーションには重大な欠陥がありました。



-おそらく、最大の不便は、すべてのコンテンツがアプリケーション自体に含まれていたことです。 この保管方法では、市場にある製品自体を更新せずにデータを編集および更新する可能性が排除されました。 さらに、これによりアプリケーションのサイズが大幅に増加しました。



-アプリケーションは使用するのが非常に不便でした。 わかりやすくするために、ストリームを表示するには、Apple TVリモコンのボタンを4回押して、ボタンを5回押す必要がありました。



-このような仮想旅行はApple TVのユーザーのみが利用可能であり、これは社会の大部分ではありません。



これらの問題を理解し、それらを解決する方法を探し始め、その結果、いくつかの目標を設定しました。



1)インターフェイスを変更し、より直感的にします。

2)サーバー側を変更して、すべてのコンテンツを保存するだけでなく、統計情報も提供します。これにより、人気のあるカメラやトップカメラを少なくとも強調表示できます。

3)もちろん、アプリケーションをiPhoneおよびiPadに適合させてください。つまり、より多くの人が仮想旅行にアクセスできるようにします。



目標が設定されました-行動する時が来ました。



ユーザーフレンドリーなインターフェースを作成する



Appleのデバイスのユーザーに便利で美しいアプリケーションを作成する方法を最もよく知っているのは誰ですか? もちろん、アップル。 私たちが探していた解決策は、表面、またはむしろ、Apple TVのメイン画面にありました。私たちは、独自のFilmsアプリケーションについて話していました。 私たちの製品は同様のコンテンツを持ち、メーカーのUXソリューションは誰もが知っているので、すべてをこのモデルに可能な限り近づけたいと考えました。



ユーザーが「映画」アプリケーションに入ると、最初に何が表示されますか? コレクションと人気映画のスクリーン。 Webcam World Viewでは、ほぼ同じことをしたかった-メイン画面上のすべての最高のカメラ。 したがって、次のステップは、メイン画面にAppleの「カルーセル」のアナログを作成することでした。







そのため、要素が視差効果を持つ、自動的に移動するカルーセルを取得する必要がありました。 基礎はクラスUICollectionViewでした。



最初に、将来のカルーセルのセル用にクラスが作成されました。



class TopCollectionViewCell: UICollectionViewCell { //    —    @IBOutlet weak var backImageView: UIImageView! override func awakeFromNib() { super.awakeFromNib() backImageView.contentMode = .scaleAspectFill backImageView.clipsToBounds = true backImageView.layer.cornerRadius = CGFloat(10.0) } override func prepareForReuse() { super.prepareForReuse() }
      
      





フォーカスがカルーセル要素に移動した瞬間に、結果として取得したいインデントの高さだけセルを下に移動します(値ledgeHeightを指定)。



  override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { if (self.isFocused) { //    ,     UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseOut, animations: { self.transform = CGAffineTransform(translationX: CGFloat(0.0), y: ledgeHeight) }, completion: nil) //   self.backImageView.clipsToBounds = true self.backImageView.adjustsImageWhenAncestorFocused = true } else { //      UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseOut, animations: { self.transform = CGAffineTransform(translationX: CGFloat(0.0), y: CGFloat(0.0)) }, completion: nil) self.backImageView.clipsToBounds = true self.backImageView.adjustsImageWhenAncestorFocused = false } }
      
      





したがって、カルーセル要素には視差効果があり、フォーカスに切り替えると、アップルのカルーセル要素と同じスタイルになります。



その後、別のタスク-カルーセルの移動の実装に続きました。 そもそも、何が欲しいかを決めました。



まず、カルーセルをループさせることにしました(最後の要素から前方に移動する場合は最初に移動し、最初の要素から後方に移動する場合は最後に移動します)。



次に、カルーセルの要素に焦点が合っていない場合、一定期間後にカルーセルの自動移動を実現する必要がありました。



カルーセルをループできるように、最初と最後の要素に対応する2つのセルの「バッファー」を追加しました。



UICollectionView要素間のように、「内部」要素をナビゲートするのが標準でした。 「外部」要素(最初と最後)からの遷移は、コンテンツのシフトとともに発生しました。



  func jump(direction: Direction) { // direction —  ,    let currentOffset = self.contentOffset.x var offset = CGFloat(count) * (collectionViewLayout as! Layout).totalItemWidth if case .backward = direction { offset *= -1 } self.setContentOffset(CGPoint(x: currentOffset + bffset, y: self.contentOffset.y), animated: false) }
      
      





自動カルーセルの移動では、単純なタイマーが使用され、再びコンテンツが最初から望ましい量だけシフトされました。



 if let initialOffset = (self.collectionViewLayout as! Layout).offsetForItemAtIndex(index: item) { self.setContentOffset(CGPoint(x: initialOffset, y: self.contentOffset.y), animated: animated) }
      
      





そこで、自動移動機能を備えたかなりアップル風のカルーセルを手に入れました。



次に、メイン画面のメインスペースを埋めることに進みました。



コンテンツをコレクションに分割することが決定されました。これらは「映画」アプリケーションで見られるものと同様の「行」でもあります。 したがって、質問が発生しました:それらを実装する方法? 問題は、コレクション(垂直方向にスクロール)と選択したコレクション内のカメラ(水平方向にスクロール)の両方をナビゲートする機能が必要だったことです。



この問題を解決するには、TableViewを使用します。TableViewの各セルには、カスタムCollectionViewがあります。 メインコントローラーはデリゲートおよびデータソースとして機能します。







異なるテーブルセルのコレクションを区別できるようにするには、タグプロパティを使用します。コレクションが配置されているテーブルセルの番号を書きます。



テーブルセルにデリゲート、データソース、および現在のコレクション番号を設定するには、setCollectionViewDataSourceDelegate関数を追加します。



 class LineTableViewCell: UITableViewCell { //  @IBOutlet weak var lineNameLabel: UILabel! //   @IBOutlet weak var lineCollectionView: UICollectionView! override func awakeFromNib() { super.awakeFromNib() ... } } extension LineTableViewCell { func setCollectionViewDataSourceDelegate <D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>> (dataSourceDelegate: D, forRow row: Int) { lineCollectionView.delegate = dataSourceDelegate lineCollectionView.dataSource = dataSourceDelegate lineCollectionView.tag = row lineCollectionView.reloadData() } }
      
      





これで、テーブルのwillDisplayメソッドで呼び出すことができます。



 func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { guard let tableViewCell = cell as? LineTableViewCell else { return } tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row) }
      
      





標準のデリゲートメソッドUITableViewとUICollectionViewを追加することで、必要なものを得ました-コンテンツはコレクションに分割されました。 カテゴリ別にコレクションを表示する画面で作業するとき、テーブルセルのコレクションで同じトリックを使用しました。



他の画面の要素の実装は標準であり、問​​題は発生しませんでした。



サーバー側



したがって、インターフェースは正常に実装されました。 次に、アプリケーションのサーバー側での作業について説明します。 ここでは、サーバーを使用してアプリケーションを可能な限りカスタマイズ可能にするというアイデアがありました。



各カメラに関するすべての情報はサーバーで収集されました。 コンテンツのモデレートを便利にするために、管理パネルを作成しました。 このシステムを使用して、モデレーターはカメラに関する情報を設定および変更し、カメラを有料または無料にし、場所が変更され、機能しない場合はオフにすることができます。 開発者が参加しなくても、マーケティングの動きは可能です。



管理パネルのもう1つの機能は、サーバーからインターフェイスの外観をカスタマイズできることです。 アプリケーションには2種類のデータ表示があります。



1.最も人気のあるカメラを備えたカルーセル。

2.カメラ付き定規-水平線上に並んでおり、1つのアイデアで結合されたカメラのグループ。



サーバーから複数のカメラを追加する場合、モデレーターは各カメラに追加される特定のタグに従って、それらを手動または自動でルーラーに結合できます。



表示されているコンテンツまたはルーラーの場所を変更する必要がある場合は、この要素またはその要素を目的の場所にドラッグするだけです。



このブロックの作成にはjScrollPanelプラグインが使用されました。 jQuery + CSS-マジックなし。



さらに、ルーラー自体では、カメラを水平方向に移動できるため、モデレーターがアプリケーションから受信するデータ(ビューの数、画面上の遷移など)を考慮してシーケンスを設定できます。 同時に行われたすべての変更がアプリケーションに表示されます。







管理パネルでは、収集された統計に基づいて人気のあるカメラを定義し、自動的に作成、更新、対応するルーラー内に移動することができます。



ただし、すべてのストリームが常に使用できるわけではありません。サーバーが動作を停止し、技術的な作業が実行され、カメラが特定の時間オフになる場合や、永久に動作しなくなる場合があります。 ユーザーの非動作ストリームを表示しないと同時に、毎日動作するようにすべてのカメラを手動でチェックしないようにするために、システムに1日に1回すべてのストリームを自動的にバイパスするように指示しました。 カメラが使用できない場合、アプリケーションでのカメラの動作は一時停止され、これに関する2番目の情報がモデレーターに送信されます。



タイムラプス



最後に、最新のアップデートの作業中に見つかった別のソリューションを共有したいと思います。 各自尊心のあるアプリケーションには、 ソーシャルネットワーク上に独自のページがあります 。 しかし、写真だけを表示するのは退屈であり、アプリケーションの詳細は、ビデオコンテンツが視聴者を引き付ける必要があることを示唆しています。 いくつかの理由でプレビュー動画が機能しませんでした。 そこで、各ストリーム(タイムラプス)のアクションビデオを作成するというアイデアが生まれました。



最終的なレシピは次のようになり、かなり素晴らしいものが作成されます。



-カメラから写真を撮り、1時間ごとに24時間以内に5秒間ビデオを録画します。

-次に、再生を2回高速化し、すべてのレコードを1つにまとめて、面白いアクションカットを取得します。たとえば、タイムラプスビデオでは、魅惑的な夕日や虎の生涯の1日を見ることができます。



今後の計画



まとめると。 私たちは、プログラミングで何も理解していないモデレーターにとっても便利なシステムを作成することができました。 チームメンバーは、開発の複雑さを掘り下げたり、毎回市場でアプリケーションを更新する必要に悩まされることなく、プロジェクトをリードできます。



その結果、Apple TVの完成品が完成し、すべてのタスクを解決しました。 私たちのチームの主な成果は、サーバーパーツと管理機能の実装の成功でした。ボーナスは、UI Apple TVの標準に従って最もユーザーフレンドリーなインターフェイスの作成でした。



これから:









これを行いました:











もちろん、すべてが失敗せずに機能するわけではなく、サーバーのすべての計画が現在実装されているわけでもありません。 原則として、コードは完全なものにはなり得ないため、私たちは止まらないように努め、絶えず改善に取り組んでいます。 サーバー設定にコンテンツだけでなく、完全なビジュアルコンポーネントも実装する予定です。 画面上のルーラーに表示されるカメラの数、カメラまたはタイムラプス、各カメラの署名、またはいくつかのカメラのみですか? サーバーへのすべての質問。







管理パネルの外観の改善も検討しています。 これは、彼女が使用するのが不快になったり、何かが彼女の目を傷つけると言っているわけではありませんが、彼女は可能な限り完璧を目指して常に努力しています。



私たちはあなたのレビューを読んで喜んでいるでしょう。 ご覧いただきありがとうございます!



All Articles