【问题标题】:Realm Object-Level Notifications inside UICollectionViewCell'sUICollectionViewCell 中的领域对象级通知
【发布时间】:2017-03-23 22:58:19
【问题描述】:

我有一个包含Album 对象的集合视图。通过点击单元格内的按钮,可以收藏或取消收藏Album。按钮图像会根据 Album 是否被收藏而改变。这部分很简单并且有效。

我遇到的问题是:

  • 如果您选择一个单元格,则会出现一个新的视图控制器,该单元格中包含Album 对象。在此视图控制器中,您可以收藏或取消收藏Album 对象。 现在,当我关闭此视图控制器时,单元格中的按钮“未”根据AlbumisFavorite 属性更新。

我认为解决方案是在 UICollectionViewCell 中使用 Realm's Object-Level Notifications。因此,当您在不同的视图控制器中收藏/取消收藏 Album 时,当您返回收藏视图时,按钮是最新的。但我不知道如何添加和删除通知 - 例如在哪里添加/删除以及根据通知在哪里更新?

注意:请不要说使用collectionView.reloadData()

这是我目前所拥有的(注意评论:var notificationToken: NotificationToken? // Is this where I add the notification for Realm?):

class Album: Object {
    dynamic var title = ""
    dynamic var isFavorite = false

    convenience init(json: [String: Any]) throws {
        self.init()

        guard let title = json["title"] as? String else {
            throw SerializationError.invalidJSON("Album")
        }

        self.title = title
    }
}

protocol AlbumCollectionViewCellDelegate: class {
    func didTapFavoriteButton(_ favoriteButton: UIButton, album: Album)
}

class AlbumCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var favoriteButton: UIButton!

    weak var delegate: AlbumCollectionViewCellDelegate?
    var album: Album!

    // HELP
    var notificationToken: NotificationToken? // Is this where I add the notification for Realm?

    @IBAction func didTapFavoriteButton(_ sender: UIButton) {
        delegate?.didTapFavoriteButton(sender, album: album)
    }

    func configure(with album: Album) {
        titleLabel.text = album.title
        favoriteButton.isSelected = album.isFavorite
        self.album = album
    }
}

class FavoritesListViewController: UIViewController, AlbumCollectionViewCellDelegate {

    // MARK: - AlbumCollectionViewCellDelegate
    func didTapFavoriteButton(_ favoriteButton: UIButton, album: Album) {
        favoriteButton.isSelected = album.isFavorite
    }
}

有什么想法吗?

【问题讨论】:

    标签: ios swift notifications realm


    【解决方案1】:

    我知道你说过不要提reloadData(),但是如果视图控制器保证不在屏幕上并且会被回调到屏幕上,我会改为只调用reloadData()(或者甚至只是reload​Items(at:​ [Index​Path])传递在可见项的索引路径中)进入视图控制器的viewWillAppear(animated:) 方法。

    这比管理通知令牌集要容易得多,尤其是当视图控制器一开始就在屏幕上时,您甚至不使用通知令牌时。 :)

    话虽如此,如果你想避免手动更新视图,无论是在屏幕上还是在屏幕外,并且一直依赖通知,那么是的,Realm 的对象级通知将是最合适的功能,是的,将逻辑添加到集合视图单元子类将是最合适的。 :)

    class AlbumCollectionViewCell: UICollectionViewCell {
        @IBOutlet weak var titleLabel: UILabel!
        @IBOutlet weak var favoriteButton: UIButton!
    
        weak var delegate: AlbumCollectionViewCellDelegate?
        var album: Album!
    
        var notificationToken: NotificationToken? 
    
        @IBAction func didTapFavoriteButton(_ sender: UIButton) {
            delegate?.didTapFavoriteButton(sender, album: album)
        }
    
        override func prepareForReuse() {
            notificationToken.stop()
            notificationToken = nil
        }
    
        func configure(with album: Album) {
            titleLabel.text = album.title
            favoriteButton.isSelected = album.isFavorite
            self.album = album
    
            notificationToken = self.album.addNotificationBlock { change in
                switch change {
                case .change(let properties):
                    for property in properties {
                        if property.name == "isFavorite" {
                            self.favoriteButton.isSelected = self.album.isFavorite
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 完美运行,非常感谢您提供如此清晰的解释,非常感谢! Realm 及其背后的整个团队简直太棒了! :)
    • 哈哈太棒了!很高兴听到!别客气!我们都很高兴听到您在 Realm 度过了愉快的时光! :D
    • 我们在使用 Realm 时遇到了一个小问题(希望是我们在启动应用程序之前的最后一个问题)。我查看了Realm Tasks 的示例代码,但用例并不相似。请你看一下这个:stackoverflow.com/questions/43081852/…(谢谢!)
    【解决方案2】:

    我知道你不想被告知使用reloadData,但你考虑过reloadItems(at:[IndexPath])吗?这只会加载您首先单击的单元格...根据您的情况,这可能是一种更简单的方法。

    也就是说,我认为您会在单元格的专辑值更改时添加通知块。比如:

    var album: Album! {
        didSet {
            self.notificationToken = album.addNotificationBlock { change in
               // The block code
            } 
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多