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的开发(一)的更多相关文章

  1. 从0到1---“保多多”APP的开发(二)

    今天继续记录宝多多开发过程中的一些值得注意的知识点: 1.验证车牌格式的正则表达式函数: //车牌号验证 - (BOOL)validateCarNo:(NSString *)carNo { NSStr ...

  2. 从0到1搭建移动App功能自动化测试平台(0):背景介绍和平台规划

    本文作者: 伯乐在线 - debugtalk .未经作者许可,禁止转载!欢迎加入伯乐在线 专栏作者. 转载地址:http://blog.jobbole.com/101221/ 背景 最近新加入DJI的 ...

  3. Python爬虫入门教程 42-100 爬取儿歌多多APP数据-手机APP爬虫部分

    1. 儿歌多多APP简单分析 今天是手机APP数据爬取的第一篇案例博客,我找到了一个儿歌多多APP,没有加固,没有加壳,没有加密参数,对新手来说,比较友好,咱就拿它练练手,熟悉一下Fiddler和夜神 ...

  4. 从0到1搭建移动App功能自动化测试平台(2):操作iOS应用的控件

    转自:http://debugtalk.com/post/build-app-automated-test-platform-from-0-to-1-Appium-interrogate-iOS-UI ...

  5. 基于vue2.0的一个豆瓣电影App

    1.搭建项目框架 使用vue-cli 没安装的需要先安装 npm intall -g vue-cli 使用vue-cli生成项目框架 vue init webpack-simple vue-movie ...

  6. 用weexplus从0到1写一个app

    说明 基于wexplus开发app是来新公司才接触的,之前只是用过weex体验过写demo,当时就被用vue技术栈来开发app的开发体验惊艳到了,这个开发体验比react native要好很多,对于我 ...

  7. 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 ...

  8. Appium 从 0 到 1 搭建移动 App 功能自动化测试平台 (1):模拟器中运行 iOS 应用

    转载:https://testerhome.com/topics/4960 在上一篇文章中,我对本系列教程的项目背景进行了介绍,并对自动化测试平台的建设进行了规划. 在本文中,我将在已准备就绪的iOS ...

  9. (转载)安卓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 ...

随机推荐

  1. win10查看连接过的wifi密码

    cmd窗口 运行   “netsh wlan show profiles name="linasd" key=clear”

  2. Linux下的PostgreSQL简单安装手册

    1. 安装环境     linux版本: CentOS release 6.2 (Final)     pg版本    : postgresql-9.5.0   2. pg数据库下载地址 --http ...

  3. oracle 金额格式化

    一般金额要显示成 XXX,XXX,XXX.XX的格式,可以这样做: to_char(column, 'FM999,999,999,990.00')

  4. R实战之热点图(HeatMap)

    快速实现是搜索帮助文档的首要目的,所以此处涉及实战的文章一概略去传统帮助文档的理论部分,直接上代码加注释! 本文将介绍R语言下利用ggplot2包制作heatmap的代码 -------------- ...

  5. winform开发框架之模块维护

    前言:模块维护试图解决的问题, 模块加载只用MEF的方式: MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库. 应用程序开发人员可利用该库 ...

  6. 利用backtrace和objdump进行分析挂掉的程序

    转自:http://blog.csdn.net/hanchaoman/article/details/5583457 汇编不懂,先把方法记下来. glibc为我们提供了此类能够dump栈内容的函数簇, ...

  7. Struts2拦截器初涉

    Struts2拦截器初涉 正在练习struts,本例是从一个pdf上摘抄的例子,那本pdf都不知道叫什么名字,不过感觉很适合初学者. 在这里要实现一个简单的拦截器"GreetingInter ...

  8. SQL Server 查询表的记录数(3种方法,推荐第一种)

    http://blog.csdn.net/smahorse/article/details/8156483 --SQL Server 查询表的记录数 --one: 使用系统表. SELECT obje ...

  9. java编写一个可以上、下、左、右移动的坦克

    唉,本人学习进度缓慢,但依然会坚持不懈!有感兴趣的朋友可以在下面留言. 源代码献上: /* * 画出我的坦克,使他可以上下左右移动 */package com.test4; import javax. ...

  10. iOS 推送通知处理

    //这是程序杀死后再通过点击通知进入时调用的方法 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOpti ...