MobileOA第一期总结
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
MobileOA第一期总结的更多相关文章
- 豪斯课堂K先生全套教程淘宝设计美工第一期+第四期教程(无水印)
第一期课程包括 <配色如此简单> <配色的流程><对称之美>第二期课程包括 <字体的气质及组合><平衡及构图形式><信息的筛选与图片的 ...
- 复旦大学EWP菁英女性课程(复旦卓越女性课程改版后第一期) _复旦大学、女性课程、高级研修班、心理学、EWP_培训通课程
复旦大学EWP菁英女性课程(复旦卓越女性课程改版后第一期) _复旦大学.女性课程.高级研修班.心理学.EWP_培训通课程 复旦大学EWP菁英女性课程(复旦卓越女性课程改版后第一期) 学 ...
- IT资源关东煮第一期【来源于网络】
IT资源关东煮第一期[来源于网络] 地址:http://geek.csdn.net/news/detail/128222
- [转]ZooKeeper学习第一期---Zookeeper简单介绍
ZooKeeper学习第一期---Zookeeper简单介绍 http://www.cnblogs.com/sunddenly/p/4033574.html 一.分布式协调技术 在给大家介绍ZooKe ...
- _00020 妳那伊抹微笑_谁的异常最诡异第一期之 SqlServer RSA premaster secret error
博文作者:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 博文标题:_00020 妳那伊抹微笑_谁的异常最诡异第一期之 SqlServer RSA premas ...
- 【每天五分钟大数据-第一期】 伪分布式+Hadoopstreaming
说在前面 之前一段时间想着把 LeetCode 每个专题完结之后,就开始着手大数据和算法的内容. 想来想去,还是应该穿插着一起做起来. 毕竟,如果只写一类的话,如果遇到其他方面,一定会遗漏一些重要的点 ...
- wussUI v1.0.0小程序UI组件库 第一期开发已完成
经过了两个月不到的开发时间,我们phonycode团队顺利的发布了小程序的UI组件库 wuss-ui 的第一个版本.目前大体预览如下 介绍 wussUI 现在有大概27个组件左右, 目前基础组件都有了 ...
- ZooKeeper学习第一期---Zookeeper简单介绍
一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技术.那么什么是分布式协调技术?那么我来告诉大家,其实分布式协调技术主要用来解决分布式环境当中多个进程之间的同 ...
- 即将放出ITSEC第一期所有培训视频
课程大概被分为三个章节 客户端安全培训 安全工具培训 服务端安全培训 部分PPT 详细课程表 FireBug代码调试工具使用:工具介绍 FireBu ...
随机推荐
- 安卓handler、thread实现异步任务
[转]http://blog.csdn.net/lanpy88/article/details/6659630 一Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI. ...
- UVa 10405 & POJ 1458 Longest Common Subsequence
求最长公共子序列LCS,用动态规划求解. UVa的字符串可能含有空格,开始用scanf("%s", s);就WA了一次...那就用gets吧,怪不得要一行放一个字符串呢. (本来想 ...
- Jenkins中deploy插件的deploy war/ear to a container与deploy artifacts to maven reepository区别
deploy war/ear to a container:发布war包到服务器 deploy artifacts to maven reepository:发布到maven服务器
- XML解析之DOM解析技术案例
Java代码: package com.xushouwei.xml; import java.io.File; import javax.xml.parsers.DocumentBuilder; im ...
- 兼容ie6及以上和firefox等标准浏览器的表格行滑过时背景色切换的效果
一.js代码——"tablehover.js" /** *②.表格单元行滑过时高亮样式动效组件封装 *oop形式封装交互动效类 *组件说明这个组件是为 ...
- 关于bootstrap的modal弹出层嵌套子Modal所引发的血案(转)
原文地址 http://blog.csdn.net/liuxiaogangqq/article/details/51821359 bootstrap的弹出层嵌套有一个问题 ,当子modal关闭时父的m ...
- Discuz经典函数注释之authcode
Discuz函数中最经典的函数是authcode函数,因为supesite,UCenterHome,UCenter,Discuz X都使用了这个函数进行加密啊传输串与cookie 今天为大家带来aut ...
- [ Android 五种数据存储方式之三 ] —— SQLite存储数据
SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能.此外它还是开源的,任何人都可以使用它.许多开源项目((Mozilla, PHP, Python)都使用了 ...
- 验证浏览器是否安装已flash插件的js脚本
function flashChecker() { var hasFlash = 0; //是否安装了flash var flashVersion = 0; //flash版本 if(document ...
- 排名前10的H5、Js 3D游戏引擎和框架
由于很多人都在用JavaScript.HTML5和WebGL技术创建基于浏览器的3D游戏,所有JavaScript 3D游戏引擎是一个人们主题.基于浏览器的游戏最棒的地方是平台独立,它们能在iOS.A ...