从0到1---“保多多”APP的开发(一)
2015年8月份,我正式接手了公司保多多APP的开发(和另一个同事一起)。
我之前并没有过从0开始创建一款APP,这次能有这样的机会,实在让我感到兴奋。因为我相信,作为这款APP的主要开发人员,在这一过程中我一定能学到太多我之前没有接触过的技术。而且从目前的进度来看,我的想法没有错。今天我主要想记录一些开发这款APP的心得,虽然APP尚未完成,但确实感触颇多。
以下内容均为最新版xcode6.4上的
首先,我们创建一个程序的启动界面,就是你点击一个APP后看到的一个界面,这个界面一般是一张关于APP的背景图,APP的名称以及版权所属公司。我们可以在LaunchScreen.xib中用UIImageView和一些label完成这个界面。
启动界面之后,我们便可以进入Main.storyboard,这是程序的主入口,一般这个里面是写用户登录的信息。在保多多中,这个界面是让用户填写登录名和密码的(也有忘记密码的按钮)。可以在stroyboard里面添加多个视图控制器,并实现它们之间的跳转关系,但是在保多多中我们没有这么做。我们只在其中添加了一个视图控制器,命名为SignInViewController。注意这里要同时在工程中创建一个同名的类,在这个类中实现逻辑代码,要注意的是,在stroyboard中要将该视图控制器与SignInViewController这个类相关联。在SignInViewController类中,我们要实现用户输入用户名和密码后的登录,核心代码:
- (void) signInAction { if ([self.userNameText.text isEqualToString:@""]) { [self showAlertView:@"用户名不能为空"]; return; } if ([self.passwordText.text isEqualToString:@""]) { [self showAlertView:@"密码不能为空"]; return; } [NetworkUtil signInApplicationWithUsername:self.userNameText.text andPassword:self.passwordText.text onSuccess:^(BOOL successful, NSDictionary *message) { //NSLog(@"message:%@",message); NSDictionary *resultMes = message[@"resultMessage"]; NSString *errorMes = resultMes[@"errorMessage"]; ) { [self showAlertView:errorMes]; return ; } NSDictionary *data = message[@"data"]; NSString *ID = data[@"UserID"]; User *user; if (ID) { user = [[User alloc] initWithID:ID]; } //属性设置 [user setValuesForKeysWithDictionary:data]; self.easeInsurance.user = user; NSUserDefaults *uds = [NSUserDefaults standardUserDefaults]; [uds setObject:self.userNameText.text forKey:UserDefaults_USERNAME]; [uds setObject:self.passwordText.text forKey:UserDefaults_PASSWORD]; [uds synchronize]; [self.navigationController pushViewController:self.easeInsurance.mainTabBarController animated:YES]; } onFailure:^(NSError *error) { }]; }
填写完用户名和密码之后,我们用一个网络请求来判断二者是否一致,如果不一致就返回错误信息,如果一致就登录成功,跳转到mainTabBarController。那么问题来了,这个mainTabBarController在哪里在什么时候初始化的?
原来,在项目中有一个AppDelegate类,程序执行时这里面的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
rerurn YES;
}方法会最先执行,在保多多中,我们在这个类里面加了个方法:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[EaseInsurance instance] launchService];
return YES;
}
这里的EaseInsurance又是什么?这个EaseInsurance类,我们称它为公共服务类,并将它设计为单例,里面放一些全局的变量并进行一些初始化工作。全局的变量有:
@property (retain) User *user;//User类,代表着用户,里面有用户所有的信息
@property (retain) UITabBarController *mainTabBarController;//分栏控制器
@property (retain) UIColor *mainColor;//APP中用到的主要的颜色
@property (assign) CGSize kScreenSize;//动态获取设备尺寸
@property (retain) NSMutableDictionary* htmlDict;//存放程序中所有的h5接口
这样,我们就明白了,我们是在AppDelegate类中,调用EaseInsurance的launchService方法,从而完成程序的一些初始化工作,而具体的初始化方法分为两个:
- (void)initializeAppearance { self.mainColor = [UIColor colorWithRed:]; [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}]; [UINavigationBar appearance].backgroundColor = self.mainColor; [[UINavigationBar appearance] setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; self.kScreenSize = [UIScreen mainScreen].bounds.size; }
- (void)initializeMainTabBarController { NSDictionary *selectedTitleAttributes = @{NSForegroundColorAttributeName: self.mainColor}; QuotationViewController *quotation = [[QuotationViewController alloc] initWithNibName:@"QuotationViewController" bundle:[NSBundle mainBundle]]; quotation.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"报价" image:[[UIImage imageNamed:@"HomepageIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]selectedImage:[[UIImage imageNamed:@"HomepageSelectedIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]]; [quotation.tabBarItem setTitleTextAttributes:selectedTitleAttributes forState:UIControlStateSelected]; CarsManagementViewController *carsManagement = [[CarsManagementViewController alloc] initWithNibName:@"CarsManagementViewController" bundle:[NSBundle mainBundle]]; carsManagement.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"车辆" image:[[UIImage imageNamed:@"CarsIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"CarsSelectedIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]]; [carsManagement.tabBarItem setTitleTextAttributes:selectedTitleAttributes forState:UIControlStateSelected]; ActivityViewController *activity = [[ActivityViewController alloc] initWithNibName:@"ActivityViewController" bundle:[NSBundle mainBundle]]; activity.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"活动" image:[[UIImage imageNamed:@"ActivityIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"ActivitySelectedIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]]; [activity.tabBarItem setTitleTextAttributes:selectedTitleAttributes forState:UIControlStateSelected]; MineViewController *mine = [[MineViewController alloc] initWithNibName:@"MineViewController" bundle:[NSBundle mainBundle]]; mine.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"我" image:[[UIImage imageNamed:@"MineIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"MineSelectedIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]]; [mine.tabBarItem setTitleTextAttributes:selectedTitleAttributes forState:UIControlStateSelected]; self.mainTabBarController = [[UITabBarController alloc] init]; self.mainTabBarController.tabBar.tintColor = [UIColor clearColor]; self.mainTabBarController.viewControllers = @[quotation, carsManagement, activity, mine]; }
我们可以很清楚的看到,第一个方法主要设置一些颜色和大小,第二个方法是用来创建mainTabBarController。这一切都完成之后,我们点击SignInViewController类的登录按钮,便可以进入mainTabBarController,进入后展现在我们面前的就是mainTabBarController的第一个视图控制器QuotationViewController(首页)。
进入保多多APP后主要分为4个板块:QuotationViewController(首页),CarsManagementViewController(车辆),ActivityViewController(活动),MineViewController(我)
这四个类都是继承与一个ViewController类,这样它们就都有了一个easeInsurance属性,这个属性是整个程序中唯一的,公用的。现在ViewController类中暂时没有其他的,就这一个属性,继承了这个类后都可以获得这个属性。以后我们可能加一些其他的属性或方法进去,看需要吧。
说到APP的登录,还有一点要补充,我们都知道,现在很多APP都有快速登录的功能,就是说只要你没有点击退出登录或者注销什么的按钮,你退出程序后,再次进入就不用再次输入用户名密码了,可以直接进入APP。我们的保多多也做了这样的功能。用法很简单,在用户第一次登录时,我们用 NSUserDefaults将用户名和密码保存,当用户再次打开APP时,我们先从 NSUserDefaults中取用户名和密码,然后判断:if(userName&&userPassword),如果不为空,再做类似于SignInViewController中的网络请求,没有错误的话那么直接进入,否则就无法进入。这个方法也是写在EaseInsurance的launchService方法中,因为这里是整个程序最先执行的,如果能直接进入,那么Main.storyboard便不再加载出来。
接下来我还想说说点击退出登录按钮会执行哪些方法:
-(void) clickLogout{ self.easeInsurance.user = nil; NSUserDefaults *uds = [NSUserDefaults standardUserDefaults]; [uds removeObjectForKey:UserDefaults_USERNAME];//删除本地用户的信息 [uds removeObjectForKey:UserDefaults_PASSWORD]; [uds synchronize]; [self.navigationController popToRootViewControllerAnimated:NO]; self.easeInsurance.mainTabBarController.selectedIndex = ;//这个细节也要注意 }
可以看到每次退出登录都会将self.easeInsurance.user赋空,所以我们每次无论是普通登录还是快速登录都要在进入之前(登录的网络请求成功之后)创建一个新的User对象,并将网络请求返回的用户的信息赋给它,在将这个User赋给EaseInsurance的user属性。
好了,今天的保多多APP心得就告一段落了,项目还在进行中,以后有了新的想法还会继续更新,敬请期待!
从0到1---“保多多”APP的开发(一)的更多相关文章
- 从0到1---“保多多”APP的开发(二)
今天继续记录宝多多开发过程中的一些值得注意的知识点: 1.验证车牌格式的正则表达式函数: //车牌号验证 - (BOOL)validateCarNo:(NSString *)carNo { NSStr ...
- 从0到1搭建移动App功能自动化测试平台(0):背景介绍和平台规划
本文作者: 伯乐在线 - debugtalk .未经作者许可,禁止转载!欢迎加入伯乐在线 专栏作者. 转载地址:http://blog.jobbole.com/101221/ 背景 最近新加入DJI的 ...
- Python爬虫入门教程 42-100 爬取儿歌多多APP数据-手机APP爬虫部分
1. 儿歌多多APP简单分析 今天是手机APP数据爬取的第一篇案例博客,我找到了一个儿歌多多APP,没有加固,没有加壳,没有加密参数,对新手来说,比较友好,咱就拿它练练手,熟悉一下Fiddler和夜神 ...
- 从0到1搭建移动App功能自动化测试平台(2):操作iOS应用的控件
转自:http://debugtalk.com/post/build-app-automated-test-platform-from-0-to-1-Appium-interrogate-iOS-UI ...
- 基于vue2.0的一个豆瓣电影App
1.搭建项目框架 使用vue-cli 没安装的需要先安装 npm intall -g vue-cli 使用vue-cli生成项目框架 vue init webpack-simple vue-movie ...
- 用weexplus从0到1写一个app
说明 基于wexplus开发app是来新公司才接触的,之前只是用过weex体验过写demo,当时就被用vue技术栈来开发app的开发体验惊艳到了,这个开发体验比react native要好很多,对于我 ...
- android 7.0拍照问题file:///storage/emulated/0/photo.jpeg exposed beyond app through ClipData.Item.getUri
Android7.0调用相机时出现新的错误: android.os.FileUriExposedException: file:///storage/emulated/0/photo.jpeg exp ...
- Appium 从 0 到 1 搭建移动 App 功能自动化测试平台 (1):模拟器中运行 iOS 应用
转载:https://testerhome.com/topics/4960 在上一篇文章中,我对本系列教程的项目背景进行了介绍,并对自动化测试平台的建设进行了规划. 在本文中,我将在已准备就绪的iOS ...
- (转载)安卓6.0之前的系统 判断app是否有录音权限
卓6.0之前的系统 判断app是否有录音权限 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ...
随机推荐
- REST实战:SeverClient项目+RESTful理论
理解一个新的技术,无疑就是使用它了,下面我们就通过一个可执行的demo来展现REST的原理和使用. 一 Demo 1.1 服务器端 1 主程序MainServer.java负责启动一个REST服务组件 ...
- NodeJS的安装
1. 进入官网下载对应版本的nodejs(我选择的是32位的window7版本x86) 2. 默认路径可修改 3. install就可以安装在cmd中输入path查看路径(我的是E:\compan ...
- tomcat 内存溢出解决办法
- 【20160924】GOCVHelper 图像处理部分(1)
增强后的图像需要通过图像处理获得定量的值.在实际程序设计过程中,轮廓很多时候都是重要的分析变量.参考Halcon的相关函数,我增强了Opencv在这块的相关功能. //寻找最大的轮廓 ...
- struct内存对齐1:gcc与VC的差别
struct内存对齐:gcc与VC的差别 内存对齐是编译器为了便于CPU快速访问而采用的一项技术,对于不同的编译器有不同的处理方法. Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则: ...
- android 修改framework下资源文件后如何编译
在framework/base/core/res/res 下添加资源文件后需要先编译资源 然后编译framework 才可正常引用 进入项目根目录 cd frameworks/base/core/re ...
- 我的android学习经历38
anddroid studio的内存修改 昨天有位朋友问到了下面的一个问题 这个判断为android studio的分配的内存不够用. 据我的了解造成这个的原因主要有以下几个方面: 1.电脑的内存本来 ...
- "Resuming debugger: error during debugging loop: TypeError: firstViewRangeElement is null"
翻译过来:“重启调试器:错误调试期间循环:TypeError:firstViewRangeElement为空” 写了一个项目,其中使用到了上传图片的插件,在本地上传图片一切正常,发布到服务器却不正常了 ...
- PDO数据库抽象层
PDO的优势在于兼容性,但速度不如mysql和mysqli new PDO($dsn,$username,$passwd[,$options]) $options可以设置数据库连接属性,如: $opt ...
- Install Google Pinyin on Ubuntu 14.04
Install Google Pinyin on Ubuntu 14.04 I've been spending more and more time on Ubuntu and I'm not us ...