2017-04-12 10 views
2

これは私が何か間違っているかもしれないので、これはquestionのフォローアップです。レルム - リストからオブジェクトを削除して追加する

私のアプリにはビデオプレーヤーがあります。コレクションビューには、FavoritesVCというビデオのリストがあります。いずれかのセルをタップすると、PlayerVCという新しいビューコントローラが選択されたビデオを再生するように見えます。また、リスト全体が渡されるため、この新しいビューコントローラPlayerVCのコレクションビューからすべてのビデオを順番に見ることができます。

すべてここでうまくいきます。

問題は、私がお気に入りにしたい/ビデオを好まない場合です。私が上に投稿した質問から、私は答えからこれを使用することに決めました:

isDeletedプロパティをVideoクラスに追加します。ユーザー がビデオを好まない場合は、ビデオオブジェクトを FavoriteList.videosから削除し、そのプロパティをtrueに設定しますが、Realmに残します。 後で(アプリケーションが終了するか、ビューコントローラが が終了したとき)、 isDeletedがtrueであるすべてのオブジェクトに対して一般的なクエリを実行して削除できます(これによりヘッドレス の問題は解決します)。

セルをタップしたとき、私はこれだけFavoritesVCであれば仕事を得ることができ、私はスウィフトarrayに領域Listを変換し、PlayerVCに電力を供給するために、このarrayを使用しています。私がこれをしないで、Listからオブジェクトを取り除いて、Listを循環しようとすると、私はIndex out of range error...になる。

私はスウィフトarrayListを変換し、PlayerVC作品にそれを渡すために持っていますが、レルムを使用した場合、間違ったようだソリューション。ベストプラクティスは、この変換を行うことはありませんすることですが、この場合には、私は単にこれは、リストのために私のコードですList

を使用する方法がわからない:

/// Model class that manages the ordering of `Video` objects. 
final class FavoriteList: Object { 
    // MARK: - Properties 

    /// `objectId` is set to a static value so that only 
    /// one `FavoriteList` object could be saved into Realm. 
    dynamic var objectId = 0 

    let videos = List<Video>() 

    // MARK: - Realm Meta Information 

    override class func primaryKey() -> String? { 
     return "objectId" 
    } 
} 

私は配列にリストを変換しますそしてそのようPlayerVCを作成します。

class FavoritesViewController: UIViewController { 

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 

     if let playerVC = self.storyboard?.instantiateViewController(withIdentifier: "playerVC") as? PlayerViewController { 

      // I convert the `List` to a Swift `array` here. 
      playerVC.videos = Array(favoritesManager.favoriteList.videos) 
      playerVC.currentVideoIndex = indexPath.row 
      self.parent?.present(playerVC, animated: true, completion: nil) 
     } 
    } 
} 

これはPlayerVCの抜粋です。 FavoritesVCのセルがタップされたときにこれが作成されます:最後に

class PlayerViewControllerr: UIViewController { 
    // Array passed from `FavoritesVC`. I converted this from the `List`. 
    var videos = [Video]() 

    var currentVideoIndex: Int! 
    var currentVideo: Video { 
     return videos[currentVideoIndex] 
    } 

    // HELP 
    // Example of how to cycle through videos. This cause crash if I use the `List` instead of Swift `array`. 
    func playNextVideo() { 
     if (currentVideoIndex + 1) >= videos.count { 
      currentVideoIndex = 0 
     } else { 
      currentVideoIndex = currentVideoIndex + 1 
     } 

     videoPlaybackManager.video = currentVideo 
    } 

    // This is where I add and remove videos from the `List` 
    @IBAction func didToggleFavoriteButton(_ sender: UIButton) { 
     favoritesManager.handleFavoriting(currentVideo, from: location)  { [weak self] error in 
      if let error = error { 
      self?.present(UIAlertController.handleErrorWithMessage(error.localizedDescription, error: error), animated: true, completion: nil) 
      } 
     } 
    } 
} 

Listからオブジェクトを追加および削除するためのコード:

class FavoritesManager { 
    let favoriteList: FavoriteList 

    init(favoriteList: FavoriteList) { 
     self.favoriteList = favoriteList 
    } 

    /// Adds or removes a `Video` from the `FavoriteList`. 
    private func handleAddingAndRemovingVideoFromFavoriteList(_ video: Video) { 
     if isFavorite(video) { 
      removeVideoFromFavoriteList(video) 
     } else { 
      addVideoToFavoriteList(video) 
     } 
    } 

    /// Adds a `Video` to the `FavoriteList`. 
    /// 
    /// Modifies `Video` `isDeleted` property to false so no garbage collection is needed. 
    private func addVideoToFavoriteList(_ video: Video) { 
     let realm = try! Realm() 
     try! realm.write { 
      favoriteList.videos.append(video) 
      video.isDeleted = false 
     } 
    } 

    /// Removes a `Video` from the `FavoriteList`. 
    /// 
    /// Modifies `Video` `isDeleted` property to true so garbage collection is needed. 
    /// Does not delete the `Video` from Realm or delete it's files. 
    private func removeVideoFromFavoriteList(_ video: Video) { 
     let predicate = NSPredicate(format: "objectId = %@", video.objectId) 
     guard let index = favoriteList.videos.index(matching: predicate) else { return } 

     let realm = try! Realm() 
     try! realm.write { 
      favoriteList.videos.remove(objectAtIndex: index) 
      video.isDeleted = true 
     } 
    } 
} 

任意の考え?

答えて

1

これは、ユーザーがビデオを好まないときに何が起こりたいのかまだ分かりませんので、依然として簡潔に答えることは難しいです。

最高のユーザーエクスペリエンスを得るには、動画を視聴しても画面に表示されないようにすることはできますが、ビューコントローラーが終了するか、次の動画の再生が始まると、ビデオはfavoriteListオブジェクト。これは、videosからオブジェクトが削除されても、ユーザーが明示的にそれを却下するまで、オブジェクトがくっついている必要があることを意味します。

私はビデオがvideosから削除された場合でも、その参照はスウィフト配列に残っているためスウィフト配列にvideosを変換することで動作します理由を推測しているので、currentVideoIndex値は同期のまま。

videosオブジェクトを直接使用することは可能ですが、ユーザーが 'unfavorite'ボタンをタップしたときに突然変異させるので、 'currentIndex'を確実に保存することはできません。

この場合、事前に再生する動画を見つけ出し、その動画を参照して保存する方がよいでしょう。そうすれば、たとえvideosが突然変異したとしても、私たちはプレイリストのどこにいるのか、今後や今後再生される予定のビデオを知的に理解することができます。

プレーヤーのビューコントローラがちょうどお気に入りマネージャを必要とし、現在のビデオは、ユーザーが

class FavoritesViewController: UIViewController { 

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 

     if let playerVC = self.storyboard?.instantiateViewController(withIdentifier: "playerVC") as? PlayerViewController { 
      playerVC.favoritesManager = favoritesManager 
      playerVC.currentVideo = favoritesManager.favoritesList.videos[indexPath.row] 
      self.parent?.present(playerVC, animated: true, completion: nil) 
     } 
    } 
} 

をタップそしてプレイヤーは論理的にそれらは後でvideosリストから削除されます場合でも、アップキューにどの動画をうまくいきます上:

class PlayerViewControllerr: UIViewController { 
    var favoritesManager: FavoriteManager 

    var currentVideo: Video? { 
     didSet { setUpVideos() } 
    } 
    var nextVideo: Video? 
    var previousVideo: Video? 

    func playNextVideo() { 
     currentVideo = nextVideo 
     videoPlaybackManager.video = currentVideo 
    } 

    func playPreviousVideo() { 
     currentVideo = previousVideo 
     videoPlaybackManager.video = currentVideo 
    } 

    func setUpVideos() { 
     let videos = favoritesManager.favoritesList.videos 
     let index = videos.index(of: currentVideo) 

     var previousIndex = index - 1 
     if previousIndex < 0 { previousIndex = videos.count - 1 } 
     previousVideo = videos[previousIndex] 

     var nextIndex = index + 1 
     if nextIndex >= videos.count { nextIndex = 0 } 
     nextVideo = videos[nextIndex] 
    } 
} 

これは、ユーザーがvideosからcurrentVideoを削除終わる「こと」ことを前提に動作しますが、ユーザーが削除することはできませんnextVideoまたは彼らがcurrentVideoになるまで。いずれにしても、ビューコントローラ自体がこれらのビデオオブジェクトをインデックスとは別に強く参照しているので、これによりうまくいけばvideosをSwift配列にコピーする必要はありません。

+0

お返事ありがとうございます。これはクラッシュを修正します!しかし、私が間違っていない限り、経験はSwift配列と同じではありません。今起こっていること: 'PlayerVC'に2つのビデオがあるとしましょう。あなたが好きでない方は、 'favoriteList' - >から削除されますが、' PlayVideo'を実行した後は 'ListV'にはないので、これを' PlayerVC'に戻すことはできません。 Swiftの配列を使ったユーザーエクスペリエンスは次のようなものです:ビデオが不快であっても、 'PlayerVC'中に' favoriteList'にいなくても、サイクルを繰り返して見ることができます – JEL

+0

申し訳ありませんが、質問。しかし、最終的にSwiftの 'array'が良い選択肢ならば、それが良いのであればそれを使うこともできますか? – JEL

+0

心配はいりません!うん、それは目的にあった。私が上に書いたように、いったんそれが不快だったら、私はユーザーがいったん離れてしまえば、それは完全にそれ自身を取り除くだろうと考えました。あと、動画を退会するまで動画が動画プレーヤーの再生リストに残りたいと思っていましたか?はい。ええ、 'videos'オブジェクトの静的なコピーを作成すると、それがうまくいきます。 – TiM

関連する問題