Ясность при инициализации с требованием `Self` для SectionModelType в RxDataSources

Связывание секционированной таблицы с RxDataSources с помощью TableViewSectionedDataSource, требуются разделы, соответствующие SectionModelType.

Этот протокол SectionModelType имеет следующий инициализатор в качестве одного из это требования:

    init(original: Self, items: [Item])

Кроме того, тот же протокол обеспечивает соблюдение var items: [Item] { get }. Теперь мы можем инициализировать вспомогательную переменную массива элементов (в вышеупомянутом init) либо с original.items, либо с items, переданным в качестве параметра инициализации. Это очень сбивает с толку. Код SectionModelType не имеет комментариев.

Раздел How в README, объясняющий создание разделов именно для этого случая, говорит о создании типовых псевдонимов (для связанное значение) и массив элементов, но ни слова о следующей реализации init с original: Self :

init(original: SectionOfCustomData, items: [Item]) {
    self = original
    self.items = items
}

Хотя это может работать в структуре, то же самое в классе кричит:

Невозможно присвоить значение: «я» неизменяемо

Может ли кто-нибудь здесь объяснить, что здесь происходит и почему нам НУЖНО инициализировать Self

Наконец, есть ли другой (более чистый) способ реактивно (только в RXSwift/RxCocoa) привязать секционированное табличное представление к наблюдаемому источнику данных. например * мои ячейки и разделы имеют свою собственную модель данных, которая должна быть изменчивой (следовательно, классы) * есть несколько экранов с этим требованием для разных сущностей, поэтому я был бы заинтересован в достижении этого с помощью протоколов вместо этого и шлепнуть соответствующие данные модель с протоколом и имеют общую реализацию для RXBinding

Любые указатели, чтобы получить больше ясности в существующей реализации или достичь вышеуказанных пунктов, были бы действительно полезны. P.S.: Я уже работаю с огромной кодовой базой, которая использует Rx, поэтому отказ от использования Rx или переход на SwiftUI и т. д. — это не то, что я ищу.


person Swapnil Luktuke    schedule 19.03.2020    source источник


Ответы (1)


init(original:items:) — это инициализатор copy. Он берет уже существующий экземпляр структуры и создает новый, идентичный, за исключением того, что он изменяет то, что находится в свойстве items.

Таким образом, в объявлении протокола init(original: Self, items: [Item]) означает: «Вы передаете мне уже существующий экземпляр любого типа, который соответствует мне, протоколу, и мы создадим новый экземпляр, который скопирует его, изменив его items».

И это именно то, что делает пример. Легче увидеть, если вы соберете все это вместе, например:

protocol SectionModelType {
    associatedtype Item
    var items: [Item] { get }
    init(original: Self, items: [Item])
}
struct CustomData {
    var anInt: Int
    var aString: String
    var aCGPoint: CGPoint
}
struct SectionOfCustomData {
    var header: String
    var items: [Item]
}
extension SectionOfCustomData: SectionModelType {
    typealias Item = CustomData
    init(original: SectionOfCustomData, items: [Item]) {
        self = original
        self.items = items
    }
}

Вам решать, в вашей реализации расширения, сделать то, что они сделали: установить self в original, который является некоторым уже существующим объектом SectionOfCustomData (который разрешен в инициализаторе структуры), а затем изменить его items. И вы должны делать что-то подобное и в таком порядке, потому что, если вы этого не сделаете, вы попытаетесь инициализировать объект SectionOfCustomData, не устанавливая его свойство header, тогда как в этом случае мы гарантируется, что уже есть значение свойства header, потому что мы начинаем с уже существующего объекта SectionOfCustomData, и вы не можете создать его, без установки его свойства header.

Что касается вашего другого беспокойства, что это не скомпилируется, если это класс, а не структура: да, вы совершенно правы, но не делайте этого. Это не то, что они сказали делать. Они сказали сделать это структурой, и они имели это в виду.

person matt    schedule 19.03.2020