领域 - 从List中删除和添加对象

时间:2017-04-12 20:43:03

标签: ios swift realm realm-list

这是question的后续行动,因为我可能做错了。

我的应用中有一个视频播放器。集合视图中有一个名为FavoritesVC的视频列表。如果您点击其中一个单元格,则会出现一个名为PlayerVC的新视图控制器来播放所选视频。此外,您可以在此新视图控制器PlayerVC中循环浏览集合视图中的所有视频,因为整个列表都已通过。

这里的一切都很好。

问题在于我想要收藏/不喜欢视频。从我上面发布的问题开始,我决定在答案中使用这个:

  

将一个isDeleted属性添加到Video类。当用户   不喜欢视频,从中删除Video对象   FavoriteList.videos,将该属性设置为true,但将其保留在Realm中。   稍后(当应用退出或视图控制器时)   被解雇),然后你可以对所有对象做一般查询   isDeleted是真的然后删除它们(这解决了无头   问题)。

如果在FavoritesVC中点击一个单元格,我只能将领域List转换为Swift array并使用此array,我才能使其正常工作为PlayerVC提供动力。如果我不这样做,并且我从List删除了一个对象,并且我尝试在List之间循环,我会得到Index out of range error... < / p>

解决方案我必须将List转换为Swift array并将其传递给PlayerVC,但在使用Realm时似乎有误。最佳做法是从不进行此转换,但在这种情况下,我不知道如何简单地使用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"
    }
}

我将List转换为数组并像这样创建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 个答案:

答案 0 :(得分:1)

这仍然很难简明扼要地回答,因为我仍然不确定当用户“不喜欢”时你想要发生什么。视频。

为了获得最佳用户体验,我认为不喜欢视频仍会让它在屏幕上播放,但一旦视频控制器被解除,或者下一个视频开始播放,视频就会被完全从{{{ 1}}对象。这意味着即使从favoriteList中删除它,videos对象也需要保持不变,直到用户明确解除它为止。

我猜测将Video转换为Swift数组的原因是因为即使视频从videos中删除,其引用仍保留在Swift数组中,因此{ {1}}值保持同步。

应该可以直接使用videos对象,但是当用户点击“不喜欢”对象时,您可以对其进行变异。按钮,您无法可靠地存储&#39; currentIndex&#39;因为这显然会改变。

在这种情况下,可能最好先确定哪些视频播放,然后存储对它们的强引用。这样,即使currentVideoIndex发生变异,我们仍然可以智能地确定我们在播放列表中的位置以及我们将播放的即将播放的视频。

播放器视图控制器只需要收藏夹管理器和用户点击的当前视频

videos

播放器将逻辑上确定要排队的视频,即使它们稍后会从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] } } ,但用户无法删除currentVideovideos,直到他们成为nextVideo。在任何情况下,既然视图控制器本身强烈地引用这些视频对象,与索引分开,这应该有希望将previousVideo复制到Swift数组中。