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心得就告一段落了,项目还在进行中,以后有了新的想法还会继续更新,敬请期待!