2017-04-12 27 views
2

由於我可能做錯了事,這是對此question的後續處理。Realm - 從列表中刪除和添加對象

我在我的應用程序中有一個視頻播放器。在收集視圖中有一個名爲FavoritesVC的視頻列表。如果點擊其中一個單元格,將會出現一個名爲PlayerVC的新視圖控制器來播放選定的視頻。此外,您可以在新視圖控制器PlayerVC中的收藏視圖中循環播放所有視頻,因爲整個列表都已通過。

這裏的一切正常。

問題是,當我想要最喜歡/不喜歡的視頻。從我上面發佈的問題中,我決定從答案中使用它:

將isDeleted屬性添加到Video類。當用戶 不利於視頻時,從 FavoriteList.videos中刪除Video對象,將該屬性設置爲true,但將其留在Realm中。 稍後(當應用程序退出或視圖控制器被解除時,視圖控制器被解除),然後可以對 isDeleted爲true的所有對象執行一般查詢,然後將其刪除(這樣可以解決無頭問題 問題)。

我只能得到當細胞被竊聽這個工作,如果在FavoritesVC,我的境界List轉換爲雨燕array並使用此arrayPlayerVC供電。如果我不這樣做,並且我從List中刪除了一個對象,並且我試圖循環訪問List,我得到一個Index out of range error...

的解決方案,我必須將List轉換爲雨燕array並傳遞至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對象,但由於您在用戶點擊'不同'按鈕時會突變它,因此您無法可靠地存儲'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,但用戶不能刪除nextVideopreviousVideo,直到他們也成爲currentVideo。在任何情況下,現在視圖控制器本身強烈引用這些視頻對象,與索引分開,這應該有希望使videos複製到Swift數組是不必要的。

+0

感謝您的回答!這修復了崩潰!然而,經驗與Swift數組不同(除非我做錯了什麼)。現在發生了什麼:假設'PlayerVC'有2個視頻。如果你不喜歡其中的一個,那麼它會從'favoriteList' - >中移除,但是現在當你執行'playNextVideo'後,你不能在'PlayerVC'中循環回去,因爲它不再在'List'中。 Swift'array'的用戶體驗是:即使視頻不合適,即使它不在'PlayerVC'中的'favoriteList'中,您仍然可以循環並再次看到它。 – JEL

+0

抱歉,如果解釋有限題。但最終如果Swift'array'是一個不錯的選擇,那麼如果這很好,我也可以使用它呢? – JEL

+0

不用擔心!是的,這是有意的。就像我上面寫的那樣,我假設一旦它不合適,一旦用戶導航,它就會完全移除。啊,所以你真的希望視頻留在視頻播放器的播放列表中,直到他們解散它爲止?好的。是的,製作'videos'對象的靜態副本對於那個很有用。 – TiM