在 Stackview 中设置项目的 ID

Posted

技术标签:

【中文标题】在 Stackview 中设置项目的 ID【英文标题】:setting ids on item in Stackview 【发布时间】:2019-08-23 10:24:14 【问题描述】:

我有一个用于创建复选框的对象数组。该模型有一个 id,名称。我创建了一个 stackView 来处理带有 id 的复选框,现在我想将选定复选框的项目附加到一个数组中,并能够在取消选择时删除它们。我能够呈现所有的观点并且效果很好

下面是我的代码

NetworkAdapter.instance.getFeaturesAmeneities()
            .subscribe(onNext: feat in
                guard let data  = feat.data else return
                self.features.append(contentsOf: data)

                self.stackFeature.axis = .vertical
                self.stackFeature.distribution = .fill
                self.stackFeature.spacing = 8

                data.forEach 
                    print($0.id)
                    self.stv = CheckboxStackView()
                    self.stv?.label.text = $0.name
                    self.stv?.checkBox.tag = $0.id ?? 0
                    self.stackFeature.addArrangedSubview(self.stv!)
                

            ).disposed(by: disposeBag)

感谢任何帮助

【问题讨论】:

【参考方案1】:

为了回答这个问题,我们首先必须使堆栈视图具有反应性和声明性。这意味着我们必须能够使用单个分配设置视图,并且需要成为观察者。这就像 RxCocoa 库对 UICollectionView、UITableView 和 UIPickerView 所做的一样。

编写函数有点高级。首先,我们从上面的其他视图中获取签名来定义函数的形状。

func items<Sequence: Swift.Sequence, Source: ObservableType>(_ source: Source) -> (_ viewForRow: @escaping (Int, Sequence.Element, UIView?) -> UIView) -> Disposable where Source.Element == Sequence

以上内容可能看起来令人生畏。它是一个函数,它接受序列的源序列并返回一个函数,该函数接受一个用于组装视图的闭包并返回一个 Dispoable。

完成的函数如下所示:

extension Reactive where Base: UIStackView 

    func items<Sequence: Swift.Sequence, Source: ObservableType>(_ source: Source) -> (_ viewForRow: @escaping (Int, Sequence.Element, UIView?) -> UIView) -> Disposable where Source.Element == Sequence 
        return  viewForRow in
            return source.subscribe  event in
                switch event 
                case .next(let values):
                    let views = self.base.arrangedSubviews
                    let viewsCount = views.count
                    var valuesCount = 0
                    for (index, value) in values.enumerated() 
                        if index < viewsCount 
                            // update views that already exist
                            _ = viewForRow(index, value, views[index])
                        
                        else 
                            // add new views if needed
                            let view = viewForRow(index, value, nil)
                            self.base.addArrangedSubview(view)
                        
                        valuesCount = index
                    
                    if valuesCount + 1 < viewsCount 
                        for index in valuesCount + 1 ..< viewsCount 
                            // remove extra views if necessary
                            self.base.removeArrangedSubview(views[index])
                            views[index].removeFromSuperview()
                        
                    
                case .error(let error):
                    fatalError("Errors can't be allowed: \(error)")
                case .completed:
                    break
                
            
        
    

上面可以这样使用:

self.stackFeature.axis = .vertical
self.stackFeature.distribution = .fill
self.stackFeature.spacing = 8

let features = NetworkAdapter.instance.getFeaturesAmeneities()
    .map  $0.data 
    .share(replay: 1)

features
    .bind(onNext:  [weak self] in self?.features.append(contentsOf: $0) )
    .disposed(by: disposeBag)

features
    .bind(to: stackFeature.rx.items)  (row, element, view) in
        let myView = (view as? CheckboxStackView) ?? CheckboxStackView()
        myView.label.text = element.name
        myView.checkBox.tag = element.id ?? 0
        return myView
    
    .disposed(by: disposeBag)

【讨论】:

您好,感谢您的回复。我收到以下错误 Generic parameter 'Sequence' is not used in function signature'Element' is not a member type of 'Source' 听起来您缺少where 子句。将我的代码复制/粘贴到您的项目中。 我就是这么做的 同样的事情***.com/questions/57646978/… 收到新错误Cannot convert value of type '(_) -&gt; (@escaping (Int, _.Element, UIView?) -&gt; UIView) -&gt; Disposable' to expected argument type '(Observable&lt;[LandMarkData]?&gt;) -&gt; (_) -&gt; _'

以上是关于在 Stackview 中设置项目的 ID的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 如何在水平 StackView 中设置可变数量按钮之间的间距?

如何在IOS的UIStackView中设置权重

在 Intellij 中设置 grails 项目

在共享项目中设置 AndroidResource 构建操作

如何在下拉框中设置所选项目

GraphQL:我需要在我的项目中设置啥?