Swift_Learn00『 基础知识 』首页投稿(暂停使用,暂停投稿)

Swift创建一个选择题库界面(解决TableViewCell中

2016-08-03  本文已影响436人  9ad91f89b29e

Swift创建一个选择题库界面(解决TableViewCell中Button的selected状态混乱和手势事件被截拦问题)-1

Swift创建一个选择题库界面(解决TableViewCell中Button的selected状态混乱和手势事件被截拦问题)-2

Swift创建一个选择题库界面(解决TableViewCell中Button的selected状态混乱和手势事件被截拦问题)-3

手势事件被截拦问题

通过给每个optionsBtn设置tag可以解决在Cell中不响应button的问题,现在如果要在点击optionsLabel的时候也响应button的点击事件,怎么实现呢。

Cell中View的层级关系如下:
contentView -> backView -> (optionsBtn,optionsLabel,...)```

   给optionLabel添加手势?答案是否定的,添加的手势只能是contentView的下一层,即backView(我试过了,具体为什么,我也不清楚)。思路如下:

1.给backView添加点击手势
2.通过gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool
方法获取touch,并根据touch.gestureRecognizers来判断是否截拦手势,return true为截拦,return false为不截拦。
如果你不添加手势,touch.gestureRecognizers就为nil,添加了一个UITapGestureRecognizer手势,
touch.gestureRecognizers=[UITapGestureRecognizer].
3.在响应手势的action中,通过手势在的pointX在哪个optionsLabel里来判断点击了哪一个optionsLabel,对应的就是哪一个button了```

代码如下:

//XXWDCell.swift
override func drawRect(rect: CGRect) {
    backView.layer.cornerRadius = 10
    backView.layer.masksToBounds = true
        
    //给backView添加手势
    let tag = UITapGestureRecognizer(target: self, action: #selector(XXWDCell.gestureRecognizerAction(_:)))
    self.backView.addGestureRecognizer(tag)
        
}

func gestureRecognizerAction(tag:UIGestureRecognizer) {
    //通过touch在backView中的位置,来判断是在哪个optionLabel中
    let pointX = tag.locationInView(self.backView)        
    for i in 0..<self.optionsLabel.count {            
        if self.optionsLabel[i].frame.contains(pointX) {
            let button = self.optionsBtn[i]//通过i获取相应的button
            self.selectAnswerAction(button)//调用button点击事件,相当于点击了button
        }            
    }
}

override func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if touch.gestureRecognizers == nil {
        return true
    }
    for tag in touch.gestureRecognizers! {
        if tag.isKindOfClass(UITapGestureRecognizer) {
            return false
        }
    }        
    return true  
}

这样在点击optionsLabel的时候,optionsBtn也会变化。

获取答案

1.selectAnswerAction点击事件,获取答案,并通过block的方式传给viewcontroller,为元组(Bool,String),bool为答案是否正确,string为"ABC"这样的字符串,之所以传bool就是要统计有多少个正确答案
2.updateBtnsSelectedState单选时只能选中一个:遍历optionsBtn,如果非当前选中的button,则btn.selected = false
3.answer(),简单一点就是如果是单选,只保留当前选中的,如果是多选则删除重复的。最开始就是要把第1、2、3、4个button转换成A、B、C、D,我的算法就是,你每次点击了,我就判断一下有哪些选中了,并把它add到selectedArray中,把非选中的删除。举例说明,多选,我可能先点击了D,然后点击了C,然后又点击了D要取消,然后点击了A想选A。第一次点击selectedArray = ["D"] ,第二次 ["D","C"],第三次["C"],第四次["C","A"],然后排序["A","C"],转换成string 答案AC。

//XXWDCell.swift
let answerList = ["A","B","C","D","E","F","G","H","I","J"]    
typealias SelectType = (Bool,String)-> ()    
var selecteAnswerBlock:SelectType?
var selectedArray:NSMutableArray = NSMutableArray()
var selecteStateArray:NSMutableArray = NSMutableArray()
@IBAction func selectAnswerAction(sender: UIButton) {
        if self.selecteAnswerBlock != nil {
            sender.selected = !sender.selected
            updateBtnsSelectedState(sender)//单选时,只能选中一个
            let answer = answer(sender)
            selecteAnswerBlock!((answer.0,answer.1))//不要写answer(sender).0,answer(sender).1这样会执行两次answer(sender)
        }
    }
    
    func updateBtnsSelectedState(sender:UIButton) {
        if model!.type == "单选" {
            let tag = 100 + model!.index.integerValue * 4
            let btns = [self.viewWithTag(tag),self.viewWithTag(tag + 1),self.viewWithTag(tag + 2),self.viewWithTag(tag + 3)]
            for view in btns {
                let btn = view as! UIButton
                if sender != btn {
                    btn.selected = false
                }
            }
        }
    }
    
    func answer(sender:UIButton) -> (Bool,String){
        var selectedAnswer:String = ""
        if sender.selected {
            if model!.type == "单选" {
                selectedArray.removeAllObjects()
                selectedArray = [self.answerList[sender.tag - 100 - model!.index.integerValue * 4]]
            }
            if model!.type == "多选" {
                selectedArray.addObject(self.answerList[sender.tag - 1000 - model!.index.integerValue * 4])
            }
        }else {
            //非选中之后删除相应的选项
            if model!.type == "单选" {
                selectedArray.removeAllObjects()
            }
            if model!.type == "多选" {
                for char in selectedArray {
                    if char as! String == self.answerList[sender.tag - 1000 - model!.index.integerValue * 4] {
                        selectedArray.removeObject(char)
                    }
                }
            }
        }
        
        //排序
        let sortedArray = selectedArray.sort { (s1, s2) -> Bool in
           return (s1 as! String) < (s2 as! String)
        }
        
        //转换成String
        for c in sortedArray {
            if model?.type == "单选" {
                selectedAnswer =  c as! String
            } else {
                selectedAnswer = selectedAnswer + (c as! String)
            }
        }
        
        //防止发生崩溃
        if sortedArray.count == 0 {
            selectedAnswer = ""
        }
        
        //防止单选后,做多选题时,会保留单选答案
        if model!.type == "单选" {
            selectedArray.removeAllObjects()
        }
        return (selectedAnswer == model?.answer,selectedAnswer)
    }

如何解决混乱的问题
混乱就是第一个cell中选中了A选项,你会发现在后面的第4、8个cell中均选中了A选项,但是第4、8个cell并没有响应button点击事件。没有响应button点击时间是好的,现在只要解决在其他cell中也出现选中的情况。

解决的办法比较原始,那就是:在tableview willdisplay方法中,先把所有的optionsBtn的selected=false,根据获得的答案来设置optionsBtn的状态,比如说,答案是ABC,如果答案中有A,就设置optionsBtn[0].selected = true以此类推。

singleChoiceArray,multipleChoiceArray分别为单选和多选的题目数组

//XXWDController.swift
var scores:Int = 0//答对题数
lazy var singleChoiceResult:NSMutableArray = {//存储单选是否正确bool
        let aArray = NSMutableArray()
        for i in 0..<self.singleChoiceArray.count {
            aArray.addObject(false)
        }
        return aArray
    }()
    
    lazy var multipleChoiceResult:NSMutableArray = {//存储多选是否正确bool
        let aArray = NSMutableArray()
        for i in 0..<self.multipleChoiceArray.count {
            aArray.addObject(false)
        }
        return aArray
    }()
    
    lazy var selectedResult:NSMutableArray = {//用来保存答案string,来判断btn的选中状态
        let aArray = NSMutableArray()
        for i in 0..<self.multipleChoiceArray.count + self.singleChoiceArray.count {
            aArray.addObject("H")//"H"其实就是给一个ABCD之外,不可能有的选项,来初始化selectedResult
        }
        return aArray
    }()


override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        //防止复用时,发生混乱,比如选中1中的A在4行中的A也在选中状态,通过重置和复置来还原
        for i in 0..<4 {
            xxwdcell.optionsBtn[i].selected = false
        }
        var idx = 0
        if indexPath.section == 0 {
            idx = indexPath.row
        }
        if indexPath.section == 1 {
            idx = indexPath.row + self.singleChoiceArray.count
        }
        //通过判断所在行的答案是否包含某个选项,来确定该optionsBtn是否被选中
        let str = self.selectedResult[idx] as! String
        if str.containsString("A") {
            xxwdcell.optionsBtn[0].selected = true
        }
        
        if str.containsString("B") {
            xxwdcell.optionsBtn[1].selected = true
        }
        
        if str.containsString("C") {
            xxwdcell.optionsBtn[2].selected = true
        }
        
        if str.containsString("D") {
            xxwdcell.optionsBtn[3].selected = true
        }
        
        //按钮回调事件
        xxwdcell.selecteAnswerBlock = {[unowned self]
            result,answ in
            if indexPath.section == 0{
                //将结果分别存储,result为Bool,answ为答案String
                self.singleChoiceResult.replaceObjectAtIndex(indexPath.row, withObject: result)
                self.selectedResult.replaceObjectAtIndex(indexPath.row, withObject: answ)
            }
            if indexPath.section == 1{
                self.multipleChoiceResult.replaceObjectAtIndex(indexPath.row, withObject: result)
                self.selectedResult.replaceObjectAtIndex(indexPath.row + self.singleChoiceArray.count, withObject: answ)
            }
        }
        
        if indexPath.section == 0 {
            //设置选择按钮的tag,防止复用时发生混乱
            for i in 0..<4 {
                xxwdcell.optionsBtn[i].tag = 100 + indexPath.row * 4 + i
            }
        }
        if indexPath.section == 1 {
            //设置选择按钮的tag,防止复用时发生混乱
            for i in 0..<4 {
                xxwdcell.optionsBtn[i].tag = 1000 + indexPath.row * 4 + i
            }
        }
        xxwdcell.model = exercise
    }

上一篇下一篇

猜你喜欢

热点阅读