这是最近的一个作业练习,因为一直不知道这个博客写什么内容,就拿这个作业来展示一下,顺便分享一下我在这个项目中使用到的一些小技巧;
项目的源代码可以在我的gitHub上获得,项目地址为:https://github.com/vfanx/ZhaoJiaXiao
项目展示:
功能介绍:
1.练习模块:能即时判断答案正误,并且给出问题解析
2.考试模块:能通过设置模块设置考题数目,并且给出考试结果
3.错题模块:能够保存考试模块中的错题并且给出答案解析,错误答案以及正确答案
4.考试成绩:统计每次考试的时间和成绩
5.设置模块:即时的设置考试模块的考题数目
技巧分析:
1. 无论是那个模块都是基于数据库的数据,虽然取自与不同的表,但是数据之间还是由一定的相似性,所以我为定义了一个抽象基类的model;
所有的viewcontroller无论是否有tableview都拥有一个数据源,而且数据源的数据读取方式相似,所以我设计了一个遵守UITableViewDataSource协议的类来为所有viewcontroller提供数据,并且对其进行一定的抽象和提供一定数量的接口来保证其复用性;这里贴出datasource的代码,
1 #import <UIKit/UIKit.h> 2 3 @class DataModel; 4 typedef void(^ConfigureCell)(id item,id cell); 5 6 7 @protocol DataSource <NSObject> 8 9 @optional 10 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; 11 12 @end 13 14 15 @interface DataSource : NSObject<UITableViewDataSource> 16 17 18 @property (nonatomic,assign) BOOL tableCanEdit; 19 @property (nonatomic,weak) id<DataSource> delegate; 20 @property (nonatomic,strong) NSArray *indexArry; 21 @property (nonatomic,strong) NSMutableDictionary *itemDict; 22 23 - (instancetype)initWithTableName:(NSString *)tableName indexArry:(NSArray *)arry configureBlock:(ConfigureCell)block; 24 25 - (DataModel *)findDataModelWithIndex:(NSInteger)index; 26 - (DataModel *)findDataModelWithIndexPath:(NSIndexPath *)indexPath; 27 28 29 @end
DataSource.h
1 #import "DataSource.h" 2 #import "DataModel.h" 3 #import "DataModelBuilder.h" 4 5 6 @interface DataSource () 7 8 @property (nonatomic,copy) NSString *tableName; 9 @property (nonatomic,copy) ConfigureCell configureBlock; 10 11 @end 12 13 @implementation DataSource 14 15 - (instancetype)initWithTableName:(NSString *)tableName indexArry:(NSArray *)arry configureBlock:(ConfigureCell)block 16 { 17 self = [super init]; 18 if (self) { 19 _tableName = tableName; 20 _indexArry = arry; 21 _itemDict = [[NSMutableDictionary alloc] init]; 22 _configureBlock = [block copy]; 23 _tableCanEdit = NO; 24 } 25 26 return self; 27 } 28 - (DataModel *)findDataModelWithIndex:(NSInteger)index 29 { 30 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0]; 31 DataModel *model = [_itemDict objectForKey:indexPath]; 32 if (model == nil) { 33 model = [DataModelBuilder buildDataModelWithTableName:_tableName serialNumber:_indexArry[index]]; 34 } 35 return model; 36 } 37 38 - (DataModel *)findDataModelWithIndexPath:(NSIndexPath *)indexPath 39 { 40 DataModel *model = [_itemDict objectForKey:indexPath]; 41 if (model == nil) { 42 model = [DataModelBuilder buildDataModelWithTableName:_tableName serialNumber:_indexArry[indexPath.row]]; 43 } 44 return model; 45 } 46 47 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 48 { 49 return _indexArry.count; 50 } 51 52 53 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 54 { 55 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:_tableName forIndexPath:indexPath]; 56 cell.textLabel.font = [UIFont systemFontOfSize:13]; 57 cell.textLabel.numberOfLines = 0; 58 DataModel *model = [self findDataModelWithIndexPath:indexPath]; 59 _configureBlock(model,cell); 60 return cell; 61 } 62 63 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 64 { 65 return _tableCanEdit; 66 } 67 68 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 69 { 70 if (editingStyle == UITableViewCellEditingStyleDelete) { 71 [_delegate tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath]; 72 } 73 } 74 75 76 @end
DataSource.m
2.一个神奇的自定义控件:
由于要修改考题的数量,没有适合的控件,然后我就对UISegmentedControl进行了一个不友好的封装,定义一个UISegmentedControl,设置三个分段
分别为"-","(当前数目)","+",然后通过左右两边老控制中间标题的数字,具体代码如下;
1 #import <UIKit/UIKit.h> 2 3 @interface NumberSegmentedControl : UISegmentedControl 4 5 @property (assign,nonatomic) NSInteger numValue; 6 @property (assign,nonatomic) BOOL isCongfigure; 7 8 - (void)configureNumberSegmented; 9 10 @end
NumberSegmentedControl.h
1 #import "NumberSegmentedControl.h" 2 3 @implementation NumberSegmentedControl 4 5 - (void)configureNumberSegmented 6 { 7 if (_isCongfigure) { 8 return; 9 } 10 _numValue = [[NSUserDefaults standardUserDefaults] integerForKey:@"numValue"]; 11 NSString *temp = [NSString stringWithFormat:@"%ld",(long)_numValue]; 12 NSInteger count = self.numberOfSegments; 13 for (NSInteger i = 0; i < count; i ++) { 14 [self removeSegmentAtIndex:0 animated:NO]; 15 } 16 [self insertSegmentWithTitle:@"-" atIndex:0 animated:NO]; 17 [self insertSegmentWithTitle:temp atIndex:1 animated:NO]; 18 [self insertSegmentWithTitle:@"+" atIndex:2 animated:NO]; 19 [self addTarget:self action:@selector(segmentValueChange:) forControlEvents:UIControlEventValueChanged]; 20 self.tintColor = [UIColor grayColor]; 21 _isCongfigure = YES; 22 self.selectedSegmentIndex = 1; 23 } 24 25 - (void)segmentValueChange:(id)sender 26 { 27 if (self.selectedSegmentIndex == 1) { 28 return; 29 } 30 if (self.selectedSegmentIndex == 0 && _numValue > 0) { 31 self.numValue = _numValue-1; 32 }else if (self.selectedSegmentIndex == 2) 33 { 34 self.numValue = _numValue+1; 35 } 36 NSString *tittle = [NSString stringWithFormat:@"%ld",(long)_numValue]; 37 [self setTitle:tittle forSegmentAtIndex:1]; 38 self.selectedSegmentIndex = 1; 39 } 40 41 - (void)setNumValue:(NSInteger)numValue 42 { 43 _numValue = numValue; 44 [[NSUserDefaults standardUserDefaults] setInteger:numValue forKey:@"numValue"]; 45 } 46 47 48 @end
NumberSegmentedControl.m
写在最后的话:
第一次写技术博客不知道写什么,如果有幸这篇博文被看到的话,希望你可以顺便去下载github下载我的代码试试,应该比这篇博文写得好;
写代码时间不长,代码风格还在形成当中,逻辑上可能也有些问题,如有错误,欢迎指正,谢谢阅读.