Как мне получить доступ к свойству одного конкретного экземпляра класса модели во всех экземплярах моего класса UITableViewCell? - PullRequest
0 голосов
/ 19 июня 2020

В настоящее время я создаю приложение iOS, которое в одном из его представлений содержит UICollectionView внутри каждой строки UITableView, так что пользователь может прокручивать все представление вниз, но также может прокручивать каждую отдельную строку вправо . Например, она выглядит точно так же, как домашняя страница Spotify. Целью приложения также является воспроизведение звуковых файлов; когда вы щелкаете по одной из этих ячеек коллекции, воспроизводится звук.

Для этого я создал собственный класс UITableViewCell. UIViewController, который управляет этим представлением, ссылается на этот класс с помощью IBOutlet на UITableView, который содержит эти настраиваемые ячейки представления таблицы, а настраиваемый класс UITableViewCell ссылается на UICollectionView внутри него с помощью IBOutlet для этого UICollectionView. Затем у меня есть еще один настраиваемый класс для этих UICollectionViewCells, который имеет смысл использовать только внутри моего настраиваемого класса UITableViewCell.

Проблема в том, что я хочу знать глобально, воспроизводятся ли какие-либо звуки. Однако каждый экземпляр настраиваемого класса UITableViewCell создает свой собственный экземпляр модели, в которой существует свойство isAnythingPlaying, поэтому доступ к этому свойству сообщает мне, только если воспроизводятся какие-либо звуковые файлы внутри текущего UITableViewCell. Для ясности:

class Model {

    // (other properties would normally be here)

    var isAnythingPlaying: Bool = false

    // (other functions would normally be here)

    func getIsAnythingPlaying() {
    /*
    The problem with this method is that it will update a property (isAnythingPlaying)
    that needs to contain the same value no matter which cell of the table view 
    (CustomTableViewCell) is accessing it.

    This is just pseudocode for the real method, which works as intended.
    */

        if (somethingIsPlaying) {
            isAnythingPlaying = true
        }

        else {
            isAnythingPlaying = false
        }
    }
}

Тогда мой класс CustomTableViewCell выглядит так:

class CustomTableViewCell: UITableViewCell! {

    @IBOutlet weak var collectionView: UICollectionView!

    var customModel = Model!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        collectionView.delegate = self
        collectionView.dataSource = self

        customModel = Model()

    // (other functions would normally be here)

    }
}

extension CustomTableViewCell: UICollectionViewDelegate, 
  UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    ***************************************************************
    // at this point the value model.isAnythingPlaying will expectedly be different
    // for each instance of the UITableViewCell. If anything is playing within that
    // particular cell (row), it will be true; otherwise, false.
    ***************************************************************

}

Могу ли я что-то сделать, чтобы разрешить всем объектам CustomTableViewCell доступ к той же переменной isAnythingPlaying? Я подумал о том, чтобы поместить его в текстовый файл в комплекте и заставить код переключить текстовый файл с «истинного» на «ложное», но это казалось слишком смешным, чтобы на самом деле пытаться.

Ответы [ 2 ]

1 голос
/ 20 июня 2020

Вы можете использовать свойство static, которое вы должны установить непосредственно на Model через Model.isAnythingPlaying = true. Объявление переменной как stati c помещает это свойство в сам класс и гарантирует, что для свойства всегда будет только одно значение. Если вы хотите ссылаться на переменную stati c из экземпляра модели, вы можете ссылаться на имя класса, как я сделал выше, или использовать ключевое слово Self, обратите внимание на заглавную букву «S».

class Model {
    // static property that every instance can read/write by using Self.isAnythingPlaying
    // any object outside of the Model class can access the same value by
    // accessing the property on the class ex.  
    // if Model.isAnythingPlaying { 
    // }
    static var isAnythingPlaying: Bool = false

    func getIsAnythingPlaying() {
        return Self.isAnythingPlaying
    }
}
0 голосов
/ 20 июня 2020

В основном вам нужен синглтон. Просто иметь переменную типа bool чрезвычайно просто:

class MyModel {
    var isAnythingPlaying: Bool = false

    static let shared: MyModel = {
        let instance = MyModel()
        return instance
    }()
}

Для ссылки из вашего класса представления:

if MyModel.shared.isAnythingPlaying {
    // do something
}

В этой простой реализации ваш logi c устанавливает переменную isAnythingPlaying значение true или false может произойти где угодно.

На практике вам нужно немного больше logi c, возможно, сохраняя список идентификаторов объектов, которые воспроизводятся, поскольку вы не хотите, чтобы игрок остановился для установки значение переменной false, если играет что-то еще. Если вы применили этот подход, вы могли бы дать синглтону вычисляемую переменную:

var currentlyPlayingIDs: [Int] = []
var isAnythingPlaying {
    get {
        return !self.currentlyPlayingIDs.isEmpty
    }
}

Затем, когда элемент начинает воспроизводиться, он может обновить синглтон следующим образом:

MyModel.shared.currentlyPlayingIDs.append(self.id)

и аналогично удалите его идентификатор, когда он перестанет играть.

Вероятно, существует некоторая потребность в обработке уведомлений и публикации для несвязанных объектов, чтобы поделиться тем, что что-то изменилось. нужно будет убедиться, что изменения являются потокобезопасными, что выходит за рамки вопроса, но я подумал, что упомянул об этом.

Вот документация Apple по одноэлементному шаблону Swift:

https://developer.apple.com/documentation/swift/cocoa_design_patterns/managing_a_shared_resource_using_a_singleton

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...