MobileOA第一期总结
前段时间一直没有更新博客,好想给自己找个借口———恩,我还是多找几个吧。毕业论文、毕业照,再感伤一下,出去玩一下,不知不觉就过去几个月了。然后上个月底才重新回到学习之路,从此让我走上正轨吧。
这算是本宝宝人生中的第一个项目了,虽然分给我的两个模块都很基础,但在编写过程中,仍然出现很多问题。从编码习惯到后期的数据处理,总结一下,以后谨记。
一、问题
1、注释
这次项目过后,我才真正切身感受到注释的重要性———这次的项目有些大,一个师姐带着我编写。注释没写好,会让跟你合作的人平添各种麻烦,就连本人,到了后期,UI界面调整之后,又回过头找当初的初衷是在干嘛,浪费时间。
2、工作流逻辑
这次的OA项目,我一共写过三个模块——请假工作流,任务模块,会议模块
由于最初写的请假工作流,并没有什么太大的逻辑问题,与其他模块没有太大的关联,我只拘泥在自己的小世界里写自己的东西,结束后集成进去便无大碍。以至于,我在接到任务和工作流模块之后,也只是安心做自己的,到后来发现,这中间涉及到的方方面面,竟然与其他模块有着千丝万缕的联系,我从一开始的工作流走向与数据来源都没弄清楚,以至于在后面调接口的时候,牵扯进很多问题,甚至连UI都改了不少。
PS:可能是因为我们实验室没有专门的UI设计师,,,但至少,在以后两年的时间里,我懂得了,不要全信设计师,被坑得到最后都满脸懵逼。
3、数据渲染
由于这是第一次参与一个完整的项目,一开始便只顾着写死数据,把页面重现以为就OK了,却没有想到零零散散的数据会给后期的数据处理造成多大的麻烦,傻乎乎的甚至有些需要从后台获取的数据不知道在@interface里面声明。
4、接口调试
我的时间,大部分还是浪费在了调接口上,可能是因为我从一开始就对接口有一种莫名的恐惧感。一遇到问题,就开始怀疑自己的能力。
其次,在接口调试过程中,要学会调试,单步跟踪,清楚代码的走向,数据获取在哪一步出现了问题,到底是自己的参数问题还是后台接口的问题,不到万不得已也别怀疑接口,宝宝在被打脸n次后吸取了教训,再也不敢随便找接口的麻烦了。还好是在学校,这要是到了公司,估计再也没人愿意写我的接口了 - -
5、数据处理
刚刚开始的时候,我总是在子进程中处理数据,只拿出自己需要的字段。然而,UI只要出现一些小的变动,就得重新分析获取数据,徒增各种麻烦。
二、可重用代码
以下是我在编写过程中用到的师姐的代码,先备份一下,有时间看看。
1、后台获取数据接口
(1)可刷新(分页)
- (void)setupRefresh
{
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(headerRereshing)];
[self.tableView.mj_header beginRefreshing];
self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(footerRereshing)];
}
#pragma mark 开始进入刷新状态
- (void)headerRereshing
{
[self loadTaskList:YES];
}
- (void)footerRereshing
{
[self loadTaskList:NO];
}
#pragma mark -- 获取任务数据
- (void)loadTaskList:(BOOL)isReFresh{
if (isReFresh) {
_pageNum = 1;
}
NSString *urlStr = [NSString stringWithFormat:@"%@%@",BASE_URL,TaskList_URL];
NSDictionary *jsonParam = @{
@"telephone" : [NSUserDefaults getUserTelephone ],
@"page" : @(_pageNum),
@"pageSize" : @(10)
};
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
dispatch_queue_t myQueue = dispatch_queue_create([@"loadTaskList" UTF8String], NULL);
dispatch_async(myQueue, ^{
//请求数据
NSData *data = [WebGetDataUtil getDataByURL:[NSURL URLWithString:urlStr ] withJsonParam:jsonParam];
NSError *error;
if (data) {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error ];
NSInteger code = [[dic objectForKey:@"code"]integerValue];
if (code == 1) {
//判断服务器是否返回数据
NSError *error;
NSArray *array = [dic objectForKey:@"data"];
if(array){
//判断返回的数据是否正确解析
dispatch_async(dispatch_get_main_queue(), ^{
//前台更新ui
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSDictionary * news = nil;
NSDictionary * news1 = nil;
if (self.taskData.count >0 && array.count >0) {
news = [self.taskData objectAtIndex:(self.taskData.count - 1)];
news1 = [array objectAtIndex:array.count-1];
}
if (array.count != 0 ) {
BOOL addFlag = YES;
if (news && !isReFresh) {
//上拉加载的是后台给出的是重复数据
if ([news[@"id"]integerValue] == [news1[@"id"]integerValue]) {
addFlag = NO;
[KSToastView ks_showToast:@"已经是最后一条" duration:3.0f];
}
}
if (isReFresh) {
[self.taskData removeAllObjects];
}
if (addFlag) {
[self.taskData addObjectsFromArray:array];
}
[_tableView reloadData];
_pageNum ++;
}else{
//没有新的数据
if(!isReFresh){
[KSToastView ks_showToast:@"已经是最后一条" duration:3.0f];
}
}
if(isReFresh) {
[self.tableView.mj_header endRefreshing];
}
else {
[self.tableView.mj_footer endRefreshing];
}
});
}
else{
//数据解析有误
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSLog(@"error:%@",error);
if(isReFresh)
[self.tableView.mj_header endRefreshing ];
else [self.tableView.mj_footer endRefreshing ];
});
}
}else {
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSLog(@"error:%@",error);
if(isReFresh)
[self.tableView.mj_header endRefreshing ];
else [self.tableView.mj_footer endRefreshing ];
});
}
} else{
//网络问题
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[KSToastView ks_showToast:@"无法连接网络,请检查网络设置" duration:3.0f];
if(isReFresh){
//加载本地条目
[self.tableView.mj_header endRefreshing];
}
else [self.tableView.mj_footer endRefreshing ];
});
}});
}
(2)不可刷新
#pragma mark -- 获取后台数据
// 获取任务信息
- (void)getDetailTaskInfo {
NSString *urlStr = [NSString stringWithFormat:@"%@%@",BASE_URL, TaskDetailInfo_URL];
NSDictionary *jsonParam = @{ @"id" : @(self.taskId)};
NSLog(@"--%zd:",self.taskId);
NSLog(@"urlStr:%@",urlStr);
dispatch_queue_t queue = dispatch_queue_create([@"getDetailTaskInfo" UTF8String], NULL);
dispatch_async(queue, ^{
NSData *data = [WebGetDataUtil getDataByURL:[NSURL URLWithString:urlStr ] withJsonParam:jsonParam];
if(data){
NSError *error;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
// NSLog(@"loginDic = %@", dic);
if (dic) {
NSInteger code = [[dic objectForKey:@"code"]integerValue];
dispatch_async(dispatch_get_main_queue(), ^{
if (code == 1) {
NSDictionary *task = [dic objectForKey:@"data"];
self.taskData = task;
[self updateViewData:task];
[self setView];
}else {
[KSToastView ks_showToast:[dic objectForKey:@"msg"] duration:3.0f];
}
});
}
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[KSToastView ks_showToast:@"网络连接失败" duration:3.0f];
});
}
});
}
2、viewPager
(1)MyViewPageer.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class MyViewPager;
//@protocol MyViewPagerDelegate <NSObject>
//
//- (void)myViewPager:(MyViewPager *)viewPager controllerViews:(NSArray *)controllerArray;
//
//@end
@interface MyViewPager : UIView
@property (nonatomic) NSInteger selectedView;
+ (instancetype)viewPagerWithFrame:(CGRect)frame controllersCount:(NSArray *)controllersArray textGroup:(NSArray *)textArray;
@end
(2) MyViewPager.m
#import "MyViewPager.h"
#import "Constants.h"
@interface MyViewPager () <UIScrollViewDelegate, UIGestureRecognizerDelegate>
@property (nonatomic, strong) UIScrollView * scrollView;
@property (nonatomic, strong) NSMutableArray * controllerViews;
@property (nonatomic, strong) NSMutableArray * labelArray;
@property (nonatomic, strong) NSMutableArray * labelTextArray;
@property (nonatomic, strong) UIView * signalView;
@property (nonatomic, strong) NSMutableArray * flagArray;
@property (nonatomic) NSInteger pageNum;
@end
@implementation MyViewPager
#define PAGE_COUNT 2
#define LABEL_HEIGHT 38
#define SIGNAL_VIEW_HEIGHT 2
//#define MINUS_HEIGHT (80 + Extra_Height*IS_iOS_7)
#define MINUS_HEIGHT 40
#define WIDTH self.frame.size.width
#define HEIGHT self.frame.size.height
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self initialization];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self initialization];
}
return self;
}
- (void)initialization{
_selectedView = 0;
_signalView = [[UIView alloc]init];
_signalView.backgroundColor = GLOBAL_COLOR;
_labelArray = [NSMutableArray arrayWithCapacity:0 ];
_flagArray = [NSMutableArray arrayWithCapacity:0 ];
}
+ (instancetype)viewPagerWithFrame:(CGRect)frame controllersCount:(NSArray *)controllersArray textGroup:(NSArray *)textArray{
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
MyViewPager *viewPager = [[self alloc]initWithFrame:frame];
viewPager.pageNum = controllersArray.count;
viewPager.controllerViews = [NSMutableArray arrayWithArray:controllersArray ];
viewPager.scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, MINUS_HEIGHT, width, height - MINUS_HEIGHT)];
viewPager.scrollView.contentSize = CGSizeMake(width * viewPager.pageNum, height - MINUS_HEIGHT);
viewPager.scrollView.pagingEnabled = YES;
viewPager.scrollView.delegate = viewPager;
[viewPager addSubview:viewPager.scrollView];
[viewPager.scrollView addSubview: [controllersArray objectAtIndex: 0]];
viewPager.labelTextArray = [NSMutableArray arrayWithArray:textArray ];
UIView * backView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, width, MINUS_HEIGHT)];
backView.backgroundColor = [UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1 ];
[viewPager addSubview:backView];
CGFloat div_width = width/viewPager.pageNum;
for (int i = 0; i < viewPager.pageNum; i++) {
[viewPager.flagArray addObject:@"0"];
UILabel * label = [[UILabel alloc ]initWithFrame:CGRectMake(i*div_width, 0, div_width, LABEL_HEIGHT)];
label.text = [textArray objectAtIndex:i];
label.textColor = [UIColor lightGrayColor ];
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = [UIColor whiteColor ];//[UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1 ];
label.userInteractionEnabled = YES;
[backView addSubview:label];
label.tag = i + 301;
[viewPager addTapGesture:label];
if (i == 0) {
[viewPager.flagArray replaceObjectAtIndex:0 withObject:@"1"];
CGRect rect = CGRectMake(i*div_width, MINUS_HEIGHT - SIGNAL_VIEW_HEIGHT, div_width, SIGNAL_VIEW_HEIGHT);
viewPager.signalView.frame = rect;
[backView addSubview:viewPager.signalView ];
label.textColor = GLOBAL_COLOR;
}
[viewPager.labelArray addObject:label];
}
return viewPager;
}
- (void)addTapGesture:(UILabel *) label{
UITapGestureRecognizer * singlTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
singlTap.delegate = self;
[label addGestureRecognizer:singlTap ];
}
- (void)tap:(UIGestureRecognizer *)gestureRecognizer{
UILabel * label = (UILabel *)gestureRecognizer.view;
NSInteger tag = label.tag - 301;
CGFloat width = self.frame.size.width;
CGFloat div_width = width/self.pageNum;
CGFloat originX = tag*div_width;
if ([[self.flagArray objectAtIndex:tag] isEqualToString:@"0"]) {
[self.scrollView addSubview:[self.controllerViews objectAtIndex:tag]];
[self.flagArray replaceObjectAtIndex:tag withObject:@"1"];
}
//动画
[UIView transitionWithView:self
duration:0.3
options:UIViewAnimationOptionCurveEaseIn
animations:^{
UILabel *lastSelectedLabel = (UILabel *)[_labelArray objectAtIndex:_selectedView];
lastSelectedLabel.textColor = [UIColor lightGrayColor];
label.textColor = GLOBAL_COLOR;
_selectedView = tag;
_signalView.frame = CGRectMake(originX, MINUS_HEIGHT - SIGNAL_VIEW_HEIGHT, div_width, SIGNAL_VIEW_HEIGHT);
} completion:nil];
[_scrollView scrollRectToVisible:CGRectMake(tag*width, MINUS_HEIGHT, self.frame.size.width, self.frame.size.height - MINUS_HEIGHT) animated:YES];
}
//滑动结束
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
CGFloat width = self.frame.size.width;
CGFloat div_width = width/self.pageNum;
CGPoint offset = scrollView.contentOffset;
NSInteger currentPage = floor(offset.x/_scrollView.frame.size.width);
if ([[self.flagArray objectAtIndex:currentPage ] isEqualToString:@"0"]) {
[self.scrollView addSubview:[self.controllerViews objectAtIndex:currentPage]];
[self.flagArray replaceObjectAtIndex:currentPage withObject:@"1"];
}
for (int i = 0; i < _pageNum; i++) {
UILabel * label = (UILabel *)[_labelArray objectAtIndex:i ];
if (i == currentPage) {
label.textColor = GLOBAL_COLOR;
_signalView.frame = CGRectMake(i*div_width, MINUS_HEIGHT - SIGNAL_VIEW_HEIGHT, div_width, SIGNAL_VIEW_HEIGHT);
}else {
label.textColor = [UIColor lightGrayColor ];
}
}
}
@end