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 ...
随机推荐
- JAVA中用于处理字符串的“三兄弟”
JAVA中用于处理字符串常用的有三个类:java.lang.String.java.lang.StringBuffer.java.lang.StringBuilder,这三者的共同之处都是final类 ...
- iOS 之 Swift 新特性
支持所有C和OC的基本类型 提供了Array 和Dictionary两个强劲的集合类型 元组 可选类型 闭包 脚本特性 类型安全
- CentOS7 部署 tomcat
1. 准备tomcat账号 本着最小权限原则,新建账号来安装tomcat. 命令:useradd , passwd 2. 配置防火墙 2.1. tomcat.xml 在/etc/firewalld/s ...
- Html在网页、页面中放置Swf、Flash 背景
Html 在网页.页面中放置Swf.Flash背景: <embed src="image/index.swf" wmode=transparent style="p ...
- Raphael的鼠标over move out事件
Raphael的鼠标over move out事件 <%@ page language="java" contentType="text/html; charset ...
- ASP.NET速度优化
用过ASP.NET的人都知道吧,页面首次打开很慢,本来网站第一次启动就慢,但别的页面如果没有访问过的第一次访问也会慢. 原因:asp.net程序第一次运行需要验证数字签名,这个验证需要远程连接微软服务 ...
- 支付宝 Android 版使用的开源组件
支付宝 Android 版使用的开源组件 前言: 花了点时间整理了 支付宝 Android 客户端使用的开源组件,给需要的同学.在你不知道用什么开源框架的时候可以作下参考,毕竟支付宝是阿里的重量级产品 ...
- 如何让微信小程序快速接入七牛云
如果你确定用七牛运行小程序的话,给大家分享一个九折优惠码:61d1fd4d1 月 9 日 微信小程序正式发布,小程序终于揭开了它神秘的面纱,开发者对小程序的追捧更是热度不减.从小程序的热门应用场景来看 ...
- ubuntu下安装ssh服务器方法
由于xshell远程连接ubuntu是通过ssh协议的,所以,需要给ubuntu安装ssh服务器. 1)ubuntu安装ssh服务器 sudo apt-get install openssh-serv ...
- WebForm 全局对象、commend
Repeater的增删改 内置对象:页面之间的数据交互为什么要用这些玩意? HTTP的无状态性 Response:响应请求 Request:获取请求 Cookies:保存登录状态----------- ...