当前位置:   article > 正文

iOS 答题功能实现 —— HERO博客_ios 实现答题效果

ios 实现答题效果

上一篇简述了搭建项目框架的流程,本篇在此基础上实用,做了一个简单的类似题库答题页面。

首先看一下效果图:

 

简单阐述一下:这里没有做网络请求数据,题目数据是本地模拟服务端写的,没有做本地缓存,每次进入、上一题、下一题时去获取服务端数据,如果有选择选项或填写答案时,在上一题、下一题及退出时保存做题记录。答题页面控制器HWQuestionsVC继承基类HWBaseViewController,在HWQuestionsVC的view上添加了几个自定义视图,根据题目类型及内容布局刷新界面。下面贴上控制器HWQuestionsVC的代码,完整demo可在下面链接下载。

 

  1. #import "HWQuestionsVC.h"
  2. #import "HWQuestionsModel.h"
  3. #import "HWQuestionsFooterView.h"
  4. #import "HWAnswerView.h"
  5. #import "HWFillAnswerView.h"
  6. #import "HWAnalysisView.h"
  7. @interface HWQuestionsVC ()<HWAnalysisViewDelegate, HWQuestionsFooterViewDelegate>
  8. @property (nonatomic, strong) NSMutableArray *questionsArray;
  9. @property (nonatomic, strong) HWQuestionsModel *model;
  10. @property (nonatomic, weak) UIScrollView *scrollView;
  11. @property (nonatomic, weak) UILabel *questionlabel;
  12. @property (nonatomic, weak) HWQuestionsFooterView *footerView;
  13. @property (nonatomic, weak) HWAnswerView *answerView;
  14. @property (nonatomic, weak) HWFillAnswerView *fillAnswerView;
  15. @property (nonatomic, weak) HWAnalysisView *analysisView;
  16. @property (nonatomic, assign) NSInteger page;
  17. @property (nonatomic, assign) BOOL isCreatControl;
  18. @end
  19. @implementation HWQuestionsVC
  20. - (NSMutableArray *)questionsArray
  21. {
  22. if (!_questionsArray) {
  23. _questionsArray = [NSMutableArray array];
  24. }
  25. return _questionsArray;
  26. }
  27. - (void)viewDidLoad {
  28. [super viewDidLoad];
  29. //设置导航栏标题并添加返回按钮
  30. [self addBackBtnAndTitle:@"答题页面"];
  31. //初始化页码
  32. _page = 1;
  33. //模拟题目数据(服务端数据库)
  34. [self setQuestionsArray];
  35. //获取题目信息,每次获取当前目标题目信息
  36. [self getQuestionsInfo];
  37. }
  38. - (void)viewWillDisappear:(BOOL)animated
  39. {
  40. [super viewWillDisappear:animated];
  41. //保存做题记录
  42. [self saveProgress];
  43. }
  44. //模拟题目数据(服务端数据库)
  45. - (void)setQuestionsArray
  46. {
  47. NSArray *array = @[
  48. @{@"questionid" : @"1000", @"totalCount" : @"5", @"question" : @"如果昨天是明天的话就好了,这样今天就周五了。真实的今天可能是星期几?", @"questiontype" : @"1", @"questiontype_text" : @"单选题", @"questionselectnumber" : @"3", @"questiondescribe" : @"星期三:理想今天是星期五,昨天是星期四,真实明天是理想的昨天是星期四,真实的今天是星期三。\n星期日:理想今天是星期五,明天是星期六,真实昨天是理想的明天是星期六,真实的今天是星期日。", @"trueanswer" : @"A", @"userAnswer" : @[], @"tkselect" : @[@"A:星期三", @"B:星期四", @"C:星期五"]},
  49. @{@"questionid" : @"1001", @"totalCount" : @"5", @"question" : @"这里是问题,这道题的答案是AC。这里是问题,这道题的答案是AC。这里是问题,这道题的答案是AC。", @"questiontype" : @"2", @"questiontype_text" : @"多选题", @"questionselectnumber" : @"5", @"questiondescribe" : @"这里是答案解析,这里可以很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的。", @"trueanswer" : @"AC", @"userAnswer" : @[], @"tkselect" : @[@"A:这个选项是正确的。这个选项是正确的。这个选项是正确的。", @"B:这个选项是错误的。这个选项是错误的。这个选项是错误的。", @"C:这个选项是正确的。这个选项是正确的。这个选项是正确的。", @"D:这个选项是错误的。这个选项是错误的。这个选项是错误的。", @"E:这个选项是错误的。这个选项是错误的。这个选项是错误的。"]},
  50. @{@"questionid" : @"1002", @"totalCount" : @"5", @"question" : @"小明被老师赶出来后决定进入IT行业,日以继夜的学习C、C++...,通过不断的努力学习,小明成功入职快递公司成为一名优秀的快递员。小明的做法是正确的么?", @"questiontype" : @"3", @"questiontype_text" : @"判断题", @"questionselectnumber" : @"4", @"questiondescribe" : @"小明读了《从入门到放弃》这本书。", @"trueanswer" : @"A", @"userAnswer" : @[], @"tkselect" : @[]},
  51. @{@"questionid" : @"1003", @"totalCount" : @"5", @"question" : @"既然选择了____________,便只顾____________。", @"questiontype" : @"4", @"questiontype_text" : @"填空题", @"questionselectnumber" : @"2", @"questiondescribe" : @"参考答案:既然选择了远方,便只顾风雨兼程。", @"trueanswer" : @"", @"userAnswer" : @[], @"tkselect" : @[]},
  52. @{@"questionid" : @"1004", @"totalCount" : @"5", @"question" : @"在ARC环境下这段代码为什么不会崩溃?\n@property (nonatomic, weak) void(^block)();\n\n- (void)viewDidLoad {\n [super viewDidLoad];\n\n void(^ __weak blockA)() = ^{\n NSLog(@“just a block”);\n }\n\n _block = blockA;\n};\n\n _block();", @"questiontype" : @"5", @"questiontype_text" : @"简答题", @"questionselectnumber" : @"1", @"questiondescribe" : @"ARC 下 block 没有捕获外部变量,block 代码被放在静态代码区,程序运行后,内存地址不变。", @"trueanswer" : @"", @"userAnswer" : @[], @"tkselect" : @[]}
  53. ];
  54. self.questionsArray = [HWQuestionsModel mj_objectArrayWithKeyValuesArray:array];
  55. }
  56. //获取题目信息,每次获取当前目标题目信息
  57. - (void)getQuestionsInfo
  58. {
  59. //更新模型
  60. _model = _questionsArray[_page - 1];
  61. //创建控件
  62. if (!_isCreatControl) [self creatControl];
  63. //刷新视图
  64. [self reloadView];
  65. }
  66. //保存做题记录,做过的题由服务端存储,不需要进行本地持久化保存
  67. - (void)saveProgress
  68. {
  69. if (([_model.questiontype intValue] < 4 && ![_answerView.selectAnswer isEqualToString:@""]) || ([_model.questiontype intValue] > 3 && ![_fillAnswerView.fillAnswer isEqualToString:@""])) {
  70. NSString *qranswer = _answerView.hidden ? _fillAnswerView.fillAnswer : _answerView.selectAnswer;
  71. NSString *qrnum = _answerView.hidden ? _fillAnswerView.qrnum : _answerView.qrnum;
  72. HWLog(@"保存做题记录参数:\n试题id:%@\n页码:%ld\n填写的答案:%@\n填写的答案角标:%@", _model.questionid, _page, qranswer, qrnum);
  73. //提交服务端保存记录
  74. HWQuestionsModel *model = _questionsArray[_page - 1];
  75. [model.userAnswer removeAllObjects];
  76. model.userAnswer = [[qranswer componentsSeparatedByString:@"|"] mutableCopy];
  77. }
  78. }
  79. //创建控件
  80. - (void)creatControl
  81. {
  82. _isCreatControl = YES;
  83. //滚动视图
  84. UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, KMainW, KMainH - 113)];
  85. scrollView.showsVerticalScrollIndicator = NO;
  86. [self.view addSubview:scrollView];
  87. self.scrollView = scrollView;
  88. //问题标签
  89. UILabel *questionLabel = [[UILabel alloc] init];
  90. questionLabel.textColor = [UIColor colorWithHexString:@"#292929"];
  91. questionLabel.font = [UIFont systemFontOfSize:15.f];
  92. questionLabel.numberOfLines = 0;
  93. [scrollView addSubview:questionLabel];
  94. self.questionlabel = questionLabel;
  95. //答案选择视图,单选、多选、判断
  96. HWAnswerView *answerView = [[HWAnswerView alloc] init];
  97. [scrollView addSubview:answerView];
  98. self.answerView = answerView;
  99. //答案填写视图,填空、简答
  100. HWFillAnswerView *fillAnswerView = [[HWFillAnswerView alloc] init];
  101. [scrollView addSubview:fillAnswerView];
  102. self.fillAnswerView = fillAnswerView;
  103. //解析视图
  104. HWAnalysisView *analysisView = [[HWAnalysisView alloc] init];
  105. analysisView.delegate = self;
  106. [scrollView addSubview:analysisView];
  107. self.analysisView = analysisView;
  108. //底部视图
  109. HWQuestionsFooterView *footerView = [[HWQuestionsFooterView alloc] initWithFrame:CGRectMake(0, KMainH - 49 - 64, KMainW, 49)];
  110. footerView.delegate = self;
  111. [self.view addSubview:footerView];
  112. self.footerView = footerView;
  113. [self reloadFooterViewState];
  114. }
  115. //刷新布局
  116. - (void)reloadView
  117. {
  118. //刷新问题相关数据
  119. NSString *questionlabelText = [NSString stringWithFormat:@"(%@)%ld. %@", _model.questiontype_text, _page, _model.question];
  120. NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
  121. [paragraphStyle setLineSpacing:4.0f];
  122. NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:questionlabelText];
  123. NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:kMainColor, NSForegroundColorAttributeName, nil];
  124. [attributedString setAttributes:attrs range:NSMakeRange(0, 5)];
  125. [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [questionlabelText length])];
  126. NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:15.f], NSParagraphStyleAttributeName:paragraphStyle};
  127. CGFloat questionLabelH = [questionlabelText boundingRectWithSize:CGSizeMake(KMainW - 20, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size.height;
  128. _questionlabel.attributedText = attributedString;
  129. _questionlabel.frame = CGRectMake(10, 10, KMainW - 20, questionLabelH);
  130. //刷新答案相关数据
  131. if ([_model.questiontype intValue] < 4) {
  132. //答案选择视图,单选、多选、判断
  133. _answerView.hidden = NO;
  134. _fillAnswerView.hidden = YES;
  135. [_answerView reloadViewWithFrame:CGRectMake(0, CGRectGetMaxY(_questionlabel.frame) + 15, KMainW, 0) style:[_model.questiontype intValue] - 1 answerArray:_model.tkselect userAnswers:_model.userAnswer];
  136. }else {
  137. //答案填写视图,填空、简答
  138. _answerView.hidden = YES;
  139. _fillAnswerView.hidden = NO;
  140. [_fillAnswerView reloadViewWithFrame:CGRectMake(0, CGRectGetMaxY(_questionlabel.frame) + 15, KMainW, 0) style:[_model.questiontype intValue] - 4 answerCount:_model.questionselectnumber userAnswers:_model.userAnswer];
  141. }
  142. //刷新解析相关数据
  143. CGFloat analysisViewY = _answerView.hidden ? CGRectGetMaxY(_fillAnswerView.frame) + 10 : CGRectGetMaxY(_answerView.frame) + 20;
  144. _analysisView.frame = CGRectMake(0, analysisViewY, KMainW, 44);
  145. _analysisView.trueAnswer = _model.trueanswer;
  146. _analysisView.analysisInfo = _model.questiondescribe;
  147. [_analysisView dismissAnalysisInfo];
  148. //设置滚动区域内容
  149. _scrollView.contentSize = CGSizeMake(KMainW, analysisViewY + 44);
  150. }
  151. #pragma mark - SXQuestionsFooterViewDelegate
  152. - (void)questionsFooterView:(HWQuestionsFooterView *)questionsFooterView didClickOptionButton:(BOOL)isNextButton
  153. {
  154. //保存做题记录
  155. [self saveProgress];
  156. //更新页码
  157. isNextButton ? _page++ : _page--;
  158. //获取目标题目信息
  159. [self getQuestionsInfo];
  160. //刷新底部视图状态
  161. [self reloadFooterViewState];
  162. }
  163. //刷新底部视图状态
  164. - (void)reloadFooterViewState
  165. {
  166. UIButton *btn = (UIButton *)[self.footerView viewWithTag:500];
  167. btn.enabled = _page == 1 ? NO : YES;
  168. UIButton *otButton = (UIButton *)[self.footerView viewWithTag:501];
  169. otButton.enabled = _page == [_model.totalCount integerValue] ? NO : YES;
  170. }
  171. #pragma mark - SXAnalysisViewDelegate
  172. - (void)didClickAnaBtnInAnalysisView:(HWAnalysisView *)analysisView
  173. {
  174. [analysisView reloadViewWithUserResult:_answerView.selectAnswer showTFView:[_model.questiontype intValue] < 4];
  175. CGFloat temH = _answerView.hidden ? CGRectGetMaxY(_fillAnswerView.frame) + 10 : CGRectGetMaxY(_answerView.frame) + 20;
  176. _scrollView.contentSize = CGSizeMake(KMainW, temH + 10 + analysisView.bounds.size.height);
  177. }
  178. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  179. {
  180. [self.view endEditing:YES];
  181. }
  182. @end

 

 

Demo 下载链接:http://code.cocoachina.com/view/135213

写博客的初心是希望大家共同交流成长,博主水平有限难免有偏颇之处,欢迎批评指正。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/729167
推荐阅读
相关标签
  

闽ICP备14008679号