【问题标题】:UISegment value changing when tableview get scrolled滚动表视图时 UISegment 值发生变化
【发布时间】:2018-02-16 20:00:54
【问题描述】:

我正在使用 UISegmentControl 在表格视图中显示目标类型问题。但是,如果我在任何一个单元格中选择一个段,那么如果我滚动,一些段值会改变。我不知道如何解决。 请指导我。

单元格大小: 160px

分段色调颜色:蓝色

编码

//UIViewController
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = segTblVw.dequeueReusableCellWithIdentifier("segment", forIndexPath: indexPath) as! segmentTblCell

        return cell
    }

//UITableViewCell CLASS
class segmentTblCell: UITableViewCell {



    @IBOutlet weak var segMent: UISegmentedControl!


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

截图如下:

【问题讨论】:

  • 您能否解释一下您的细分市场在哪里?在表格单元格内?
  • 是的.. 在 UITableView 中。 Havin 10 行。
  • 我们需要你的一些代码。然而,它看起来像分段控件在单元格内。在这种情况下,当调用 tableView:cellForRowAtIndexPath 并将单元格出列时,必须初始化单元格内的所有组件。由于单元格被重复使用,您最终会得到一些组件显示其他单元格的值,而不是您想要的。
  • 我会更新我的完整代码。对不起....
  • 我更新了。请帮助我。

标签: swift uitableview uisegmentedcontrol


【解决方案1】:

由于dequeueReusableCellWithIdentifier: 的工作方式,您遇到了这个问题。每次将单元格滚动出屏幕时,它都会进入一个缓存区域,在那里它会被重复使用。

假设您有 100 个单元格。他们所有的segmentedControl 对象都设置为first。你点击一个来改变它的价值。当单元格移出视图时,它会进入缓存,如果您进一步向下滚动,它将在缓存中出列。

理解这一点很重要,因为segmentedControl 对象实际上并没有改变。由于出队行为,它看起来正在发生变化。

要解决这个问题,您需要实现一个存储segmentedControl 对象值的数据源,这样您就可以在每次单元格出列时正确地重新初始化它。

【讨论】:

  • 对于初学者,在 tableViewController 的范围内设置一个变量,该变量包含 segmentedControl 对象的值。这将是您的dataSource。当您点击segmentedControl 时,请确保更新变量中的值。您还需要根据dataSource 配置单元格 - 即变量。您需要阅读 MVC 模式
【解决方案2】:

方法一:通过将所有单元格对象保存在一个数组中来防止单元格的重复使用

var arraysCells : NSMutableArray = []//globally declare this

viewDidLoad()

for num in yourQuestionArray//this loop is to create all cells at beginning 
{
     var nib:Array = NSBundle.mainBundle().loadNibNamed("SegmentTableViewCell", owner: self, options: nil)
     var cell = nib[0] as? SegmentTableViewCell
     arraysCells.addObject(cell!);
}

在tableViewDelegate中,

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return arraysCells.objectAtIndex(indexPath.row) as! UITableViewCell
}

您可以通过迭代arraysCells找到选定的段值(答案)

注意:如果您有大量单元格,方法 1 会很慢

方法2:正常重用单元格,但使用委托和数组保存状态(输入的值)。

在自定义 UITableViewCell 中

@objc protocol SegmentTableViewCellDelegate {
func controller(controller: SegmentTableViewCell, selectedSegmentIndex:Int, indexPath : NSIndexPath)
}

class SegmentTableViewCell: UITableViewCell {

var delegate: AnyObject?
var indexPath : NSIndexPath?

@IBOutlet weak var segment: UISegmentedControl! //outlet of segmented Control

@IBAction func onSegmentValueChanged(sender: UISegmentedControl/*if the parameter type is AnyObject changed it as  UISegmentedControl*/)//action for Segment
{
    self.delegate?.controller(self, selectedSegmentIndex: sender.selectedSegmentIndex, indexPath: indexPath!)
}

在视图控制器中

class MasterViewController: SegmentTableViewCellDelegate{
var selectedAnswerIndex : NSMutableArray = []  //globally declare this
var selectedSegmentsIndexPath : NSMutableArray = [] //globally declare this


func controller(controller: SegmentTableViewCell, selectedSegmentIndex:Int, indexPath : NSIndexPath)
{
    if(selectedSegmentsIndexPath.containsObject(indexPath))
    {
        selectedAnswerIndex.removeObjectAtIndex(selectedSegmentsIndexPath.indexOfObject(indexPath))
        selectedSegmentsIndexPath.removeObject(indexPath)
    }
    selectedAnswerIndex.addObject(selectedSegmentIndex)
    selectedSegmentsIndexPath.addObject(indexPath)
}

在 cellForRowAtIndexPath(tableView 委托)中

if(selectedSegmentsIndexPath.containsObject(indexPath))
{
 cell?.segment.selectedSegmentIndex = selectedAnswerIndex.objectAtIndex(selectedSegmentsIndexPath.indexOfObject(indexPath)) as! Int
}
cell?.delegate = self
cell?.indexPath = indexPath

你可以得到结果

for index in selectedSegmentsIndexPath
{
  var  cellIndexPath = index as! NSIndexPath
  var answer : Int = selectedAnswerIndex.objectAtIndex(selectedSegmentsIndexPath.indexOfObject(cellIndexPath)) as! Int
  NSLog("You have enterd answer \(answer) for question number \(cellIndexPath.row)")
}

【讨论】:

  • 我认为这不是一个好主意,特别是如果你有大量的单元格
  • @McDonal_11 对于方法 1 .. 你会得到答案`var index : Int = 0 for cell in arraysCells { var cell:SegmentTableViewCell? = arraysCells .objectAtIndex(index) as? SegmentTableViewCell cell?.segment.selectedSegmentIndex cell?.switchAnswer.selected NSLog("问题编号(索引)的答案是 (cell?.segment.selectedSegmentIndex) 或 (cell?.switchAnswer.selected) ") index++ }`
【解决方案3】:

@KelvinLau 是完美的

你可以使用var segmentedTracker : [NSIndexPath:Int] = [:]来做到这一点

在 segmentedValueChanged 上设置 selectedIndex 的值即:segmentedTracker[indexPath] = valueOf the selected index

然后在 cellForRowAtIndexPath 中检查值 let selected = [segmentedTracker]

cell.yourSegmentedControlReference.selectedIndex = selected

请注意这是一个我不记得属性名称的伪代码。从这里你可以自己弄清楚

【讨论】:

  • 我试过这段代码。我,要实现这一目标面临一些困难。
【解决方案4】:

我认为在 UITableViewCell 中使用 UISegmentControl 可能是错误的。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UISegmentedControl_Class/

我从未在 iOS 应用程序中看到过这种情况。

问题是 UITableViewCell 被 dequeueReusableCellWithIdentifier 方法重用了。所以滚动时会改变一些 UISegmentControl 值。

虽然这不是最佳解决方案,但您可以使用静态单元格。您需要做的是只切换静态单元格。如果是这样,你就不用写 UITableViewCell 的代码了。

【讨论】:

    【解决方案5】:

    2018 年:更新答案

    UISegement inside UITableViewCell 中找到我最简单的答案

    ================================================ ========

    2015 年

    我以自己的方式进行了测试。我的编码如下。请指导我,这是正确的方式还是错误的方式?我的问题得到解决。此代码停止可重复使用的单元格。

    我的代码如下:

    //UIViewController
    var globalCell = segmentTblCell()  //CUSTOM UITableViewCell Class
    
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
            return 1
        }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = segTblVw.dequeueReusableCellWithIdentifier("segment", forIndexPath: indexPath) as! segmentTblCell
    
        globalCell  = segTblVw.dequeueReusableCellWithIdentifier("segment", forIndexPath: indexPath) as! segmentTblCell  //THIS LINE - STOPS REUSABLE TABLE.
    
        return cell
    }
    

    【讨论】:

    • 据我所知,该行不会停止可重复使用的单元格
    • 感谢@ShebinKoshy。我正在使用这个。如果我在任何一个单元格中选择一个段,那么如果我滚动,则单元格的其余部分没有变化。
    • 你在用故事板吗?
    • 我测试了你的代码,它重用了单元格,但是段中的值没有改变,我不知道为什么!!但是,如果你在单元格中添加一个 textField,你就会知道发生了什么。 .在我看来,不要这样做。因为您的应用将使用更多内存(您可以通过向下滚动并连续滚动 tableView 10 次来检查它)
    • 是的..我检查了 UItextView,,.发生了一些问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多