單選問(wèn)答題實(shí)現(xiàn)思路(UITableView方式)

公司有這么個(gè)需求, 要求用戶在線填寫單選形式的答題,效果如下:

風(fēng)險(xiǎn)評(píng)估頁(yè)面

這里要注意的是, 每題對(duì)應(yīng)的ABCD選項(xiàng)都有對(duì)應(yīng)的分?jǐn)?shù), 提交后計(jì)算總分?jǐn)?shù), 每題單選,共10道題, 并且在頁(yè)面滑動(dòng)回之前答過(guò)的題后, 要顯示之前已經(jīng)選擇過(guò)的選項(xiàng)

當(dāng)然其實(shí)這個(gè)簡(jiǎn)單的也面, 要實(shí)現(xiàn)并不難, UIScollView + 自定義UIView 容器就可以實(shí)現(xiàn), 公司安卓端就是這么實(shí)現(xiàn)的, 但是缺點(diǎn)也很顯著, 同一個(gè)頁(yè)面控件太多, 最終導(dǎo)致了項(xiàng)目崩潰

我個(gè)人在寫項(xiàng)目的時(shí)候, 能用UITableView 的時(shí)候盡量不會(huì)使用UIScrollView, 所以我第一選擇是使用UITableViewController, 但是使用不分組形式, 因?yàn)橐婚_(kāi)始看起來(lái)每道題目都是類似的界面, 做起來(lái)應(yīng)該會(huì)很簡(jiǎn)單, 原數(shù)據(jù)保存在risk.json中

以下是我一開(kāi)始的部分代碼

- (void)loadRiskData
{
#pragma mark - Table view data source
    if (!_dataArray) {
        _dataArray = [NSArray new];
        // 解析本地JSON文件獲取數(shù)據(jù),生產(chǎn)環(huán)境中從網(wǎng)絡(luò)獲取JSON
        NSString *path = [[NSBundle mainBundle] pathForResource:@"risk" ofType:@"json"];
        NSError *error = nil;
        NSData *data = [[NSData alloc] initWithContentsOfFile:path];
        
        
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
        _dataArray = [JSRiskEvaluateModel objectArrayWithKeyValuesArray:dict[@"question"]];
        
        
        cellMarkArray = [NSMutableArray array];
        for (int i = 0; i < _dataArray.count; i++)
        {
            cellMarkDic = [NSMutableDictionary dictionary];
            
            [cellMarkDic setObject:@"0" forKey:@"cellMark"];
            [cellMarkArray addObject:cellMarkDic];
        }
        NSLog(@"_dataArray.firstObject = %@ ", _dataArray);
        if (error) {
            NSLog(@"address.json - fail: %@", error.description);
        }
    }

}

在這里將risk.json中的數(shù)據(jù)解析出來(lái), 后來(lái)做著做著發(fā)現(xiàn)一個(gè)問(wèn)題, 就是我使用的是不分組形式, 一道題里的選項(xiàng),全部放在一個(gè)cell中


screenshot.png

當(dāng)你點(diǎn)擊一個(gè)cell時(shí), 在- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 方法中,沒(méi)有辦法區(qū)分你到底是選擇了哪道題, 那么你選擇的那個(gè)題目的分?jǐn)?shù)也就無(wú)法取出來(lái)

所以我又放棄了這種做法, 改為使用分組形式, 一個(gè)問(wèn)題為一個(gè)組, 一個(gè)選擇項(xiàng)為一個(gè)UITableViewCell
可是做著又發(fā)現(xiàn)一個(gè)問(wèn)題, 循環(huán)利用, cell 界面需要將你點(diǎn)擊的那道題目的按鈕變?yōu)檫x中狀態(tài), 這個(gè)狀態(tài)是要保存的, 當(dāng)你重新滾回你選擇的題目時(shí),要有之前選中的題目按鈕為選中狀態(tài), 界面不再試一個(gè)靜態(tài)的數(shù)據(jù)頁(yè)面, 你在重新滾回這個(gè)界面時(shí), 從新添加數(shù)據(jù)已經(jīng)不能滿足需求了

為了解決這個(gè)問(wèn)題

  1. 首先, 我在生成cell時(shí), 不使用循環(huán)生成,


    screenshot.png
  2. 這樣的話,生成的cell數(shù)據(jù)正確, 但是按鈕點(diǎn)擊的狀態(tài)沒(méi)法實(shí)現(xiàn), 所以我使用了字典, 每組一個(gè)字典,分別用indexpath.section 作為key, 被選擇的index.row作為value, 然后將字典按順序保存在數(shù)組中

Snip20170327_2.png

Snip20170327_1.png

根據(jù)蘋果的特性, 當(dāng)上拉或者下拉UITableViewController, 一個(gè)UITableViewCell 即將出現(xiàn)在屏幕上時(shí), 會(huì)調(diào)用- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法, 所以我們?cè)谶@里來(lái)判斷他的點(diǎn)擊狀態(tài)

這里取出數(shù)組中對(duì)應(yīng)的位置,進(jìn)行重新生成被點(diǎn)中狀態(tài)的cell狀態(tài)


if (indexPath.section == 0)
    {
        // 如果是字典類, 說(shuō)明這個(gè)組的在數(shù)組中的位置為字典, 說(shuō)明之前有點(diǎn)擊過(guò)這個(gè)組的按鈕
        if ([self.cellMarkArray[indexPath.section] isKindOfClass:[NSMutableDictionary class]] )
        {
            UITableViewCell * cell;
            NSMutableDictionary *dic = self.cellMarkArray[indexPath.section];

            if ([[dic objectForKey:@"0"] isEqualToString:@"1"])
            {
                cell = [self SelectCellOneView:indexPath andTableView:tableView andRiskModel:riskModel];
                
            }else if ([[dic objectForKey:@"0"] isEqualToString:@"2"])
            {
                cell = [self SelectCellTwoView:indexPath andTableView:tableView andRiskModel:riskModel];
                
            }else if ([[dic objectForKey:@"0"] isEqualToString:@"3"])
            {
                cell = [self SelectCellThreeView:indexPath andTableView:tableView andRiskModel:riskModel];
            }else if ([[dic objectForKey:@"0"] isEqualToString:@"4"])
            {
                cell = [self SelectCellForeView:indexPath andTableView:tableView andRiskModel:riskModel];
                
            }else
            {
                // 普通沒(méi)有被選中狀態(tài)
                cell = [self nomallCellView:indexPath andTableView:tableView andRiskModel:riskModel];
            }
            
            return cell;

        }else
        {
            // 沒(méi)有點(diǎn)擊過(guò), 就返回沒(méi)選中的cell
            // 普通沒(méi)有被選中狀態(tài)
             UITableViewCell * cell = [self nomallCellView:indexPath andTableView:tableView andRiskModel:riskModel];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            return cell;
        }

以下是示例第一個(gè)選項(xiàng)被點(diǎn)中時(shí), 生成的cell狀態(tài)

- (UITableViewCell *)SelectCellOneView:(NSIndexPath *)indexPath andTableView:(UITableView *)tableView andRiskModel:(JSRiskEvaluateModel *)riskModel
{
    if (indexPath.row == 0)
    {
        JSGotoRiskQuestionTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:questionTitle];
        
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.questionTitleStr = riskModel.questionTitle;
        return cell;
    }else if (indexPath.row == 1)
    {
        
//        JSGotoRiskCell *cell = [tableView dequeueReusableCellWithIdentifier:question];
        
        JSGotoRiskCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        
        if (cell == nil) {
            cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([JSGotoRiskCell class]) owner:nil options:nil] lastObject];
        }

        cell.line.hidden = YES;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.questionLabel.text = riskModel.questionA;
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_a_on"] forState:UIControlStateNormal];
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_a"] forState:UIControlStateSelected];
        [cell.questionBtn setSelected:YES];
        return cell;
    }else if (indexPath.row == 2)
    {
//        JSGotoRiskCell *cell = [tableView dequeueReusableCellWithIdentifier:question];
        JSGotoRiskCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        

        if (cell == nil) {
            cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([JSGotoRiskCell class]) owner:nil options:nil] lastObject];
        }
        cell.line.hidden = YES;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.questionLabel.text = riskModel.questionB;
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_b_on"] forState:UIControlStateNormal];
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_b"] forState:UIControlStateSelected];
        return cell;
    }else if (indexPath.row == 3)
    {
//        JSGotoRiskCell *cell = [tableView dequeueReusableCellWithIdentifier:question];
        JSGotoRiskCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        

        if (cell == nil) {
            cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([JSGotoRiskCell class]) owner:nil options:nil] lastObject];
        }
        cell.line.hidden = YES;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.questionLabel.text = riskModel.questionC;
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_c_on"] forState:UIControlStateNormal];
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_c"] forState:UIControlStateSelected];
        return cell;
        
    }else if (indexPath.row == 4)
    {
//        JSGotoRiskCell *cell = [tableView dequeueReusableCellWithIdentifier:question];
        JSGotoRiskCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        

        if (cell == nil) {
            cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([JSGotoRiskCell class]) owner:nil options:nil] lastObject];
        }
        if (indexPath.section == 8)
        {
            cell.line.hidden = YES;
        }else
        {
            cell.line.hidden = NO;
        }
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.questionLabel.text = riskModel.questionD;
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_d_on"] forState:UIControlStateNormal];
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_d"] forState:UIControlStateSelected];
        return cell;
    }else
    {
//        JSGotoRiskCell *cell = [tableView dequeueReusableCellWithIdentifier:question];
        JSGotoRiskCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        

        if (cell == nil) {
            cell = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([JSGotoRiskCell class]) owner:nil options:nil] lastObject];
        }
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.questionLabel.text = riskModel.questionE;
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_e_on"] forState:UIControlStateNormal];
        [cell.questionBtn setImage:[UIImage imageNamed:@"icon_e"] forState:UIControlStateSelected];
        return cell;
    }

}

有個(gè)注意點(diǎn)就是數(shù)組的插入不要使用insertObject, 我最后使用了repalceObjectAtIndex的方式將字典存放在對(duì)應(yīng)的數(shù)組位置中, 因?yàn)槲野l(fā)現(xiàn)使用insert的方式, 偶爾在來(lái)回滾動(dòng)的過(guò)程中, 生成數(shù)組時(shí)有時(shí)會(huì)取不出對(duì)應(yīng)的字典, 導(dǎo)致后面的cell重現(xiàn)變?yōu)闆](méi)有選中狀態(tài)

單選實(shí)現(xiàn)的文件已經(jīng)放在了gitHub 上, 小家可以來(lái)這里下載問(wèn)卷調(diào)查(單選)
文件暫時(shí)還沒(méi)有整理, 有點(diǎn)亂,后期有時(shí)間我會(huì)再整理, 但是不影響使用, 打開(kāi)可直接運(yùn)行, 希望對(duì)小伙伴們有用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,238評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 177,823評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,604評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,339評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,713評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評(píng)論 3 445
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,893評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,448評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,201評(píng)論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,397評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,631評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 35,033評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,321評(píng)論 1 293
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,128評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,347評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容