最近入职新公司,真心体会到代码写得好不好,对程序媛来说是多么的重要。入职的公司,老人基本不在,都是新入职的,代码量庞大,最多的类里有10000多行,整理也是个体力活,而且漏洞百出,连版本更新,导览页的处理都没有。加了处理这个工作不是我做的,看了下新同事加的代码,思路基本差不多。现在拿出来说,就当给新入行的伙伴们分享一下,少走点弯路。
我们要明确,导览页是做什么的?打个比方,你在手机上第一次安装一款软件的时候,并不是马上进入到app的主界面,比如qq空间,并不是安装了马上登录界面出现,网易新闻安装了不是马上进入新闻列表,总会有那么三到六页的介绍,简单扼要的介绍这款app 是做什么的,有哪些突出点。ok,这个就是导览页,好像很多朋友也喜欢叫新特性,意思是一样的;当一款软件,有新的功能和特性的时候,你点击更新后,app就会展示这些导览页。
说下我们公司,我们接手的app遇到的问题吧。第一个就是,进入app ,沙盒存储了一个字符串,代表着app是不是首次进入。这个是没问题的,思路也没错,但思路不严谨啊。当用户没有删除之前的app ,而是直接点击更新,手机沙盒中已经存储了之前的字符串,说不是第一次进入了,会怎么样?样子就是没有显示导览页,UI大神们苦思冥想出来的导览页,用户没看到,用户也不知道更新完了,到底有什么新功能?ok,这个问题被我们强大的测试人员测试出来了,而且的确存在着很大的不合理性,怎么解决这个问题呢?存版本号啊,对吧,大家想想对不对,每次拿当前版本和上次存储版本做对比,这样就好了,对不对?接下来会上代码,说下第二个问题。
第二个问题就是,在导览页的最后一页,总会有那么个按钮,进入主app,这个大家并不陌生。一般呢,咱们不会犯错误滴,我说的错误是什么呢?就是很多人,用push或model进行界面切换。有人问了,有什么问题,我把push的返回按钮隐藏或是把model的取消按钮隐藏,回不到导览页不就行了,只要用户看不到不就行了。ok,行,我只能勉强的说行,为什么这么说?先说push,push的控制器都在导航控制器的栈里,你push过去了,你hidden了返回按钮,但导览视图控制器还存在啊 ,没有被销毁,会出现什么问题?内存,它占用内存,不要想着ARC给你解决所有问题,想的太美好了,同理,model也是,导览视图控制器并没有真正的销毁,它存在于你的内存里,其实我们不需要它了,对不?
第三个问题,有人喜欢用collectionview做导览页,把cell之间的间距设置为0,写一大堆代理方法,美其名曰,这是为了循环利用,我想说的是,这没问题,看个人喜好。但是,导览页三到六页的图片,一个scrollview就可以搞定,你费那么大的事干嘛呢?真的没必要。
好了,现在上代码说问题吧,我个人还是习惯oc的,12年工作以来一直在用,虽然也学了swift,但是oc 比较得心应手,大家勿怪。
我直接上一下重点的代码吧。
// 创建一个scrollView:显示导览页图片
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = self.view.bounds;
[self.view addSubview:scrollView];
self.scrollView = scrollView;
// 添加图片到scrollView中
CGFloat scrollW = scrollView.width;
CGFloat scrollH = scrollView.height;
for (int i = 0; i< GuideCount; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.width = scrollW;
imageView.height = scrollH;
imageView.y = 0;
imageView.x = i * scrollW;
// 显示图片
NSString *name = [NSString stringWithFormat:@"new_guide_%d", i + 1];
imageView.image = [UIImage imageNamed:name];
[scrollView addSubview:imageView];
// 如果是最后一个imageView,就往里面添加其他内容
if (i == GuideCount - 1) {
[self setupLastImageView:imageView];
}
}
// 如果想要某个方向上不能滚动,对应的尺寸数值传0即可
scrollView.contentSize = CGSizeMake(GuideCount * scrollW, 0);
scrollView.bounces = NO; // 去除弹簧效果
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.delegate = self;
// 添加pageControl:展示目前看的是第几页
UIPageControl *pageControl = [[UIPageControl alloc] init];
pageControl.numberOfPages = GuideCount;
pageControl.backgroundColor = [UIColor redColor];
pageControl.currentPageIndicatorTintColor = CXColor(253, 98, 42);
pageControl.pageIndicatorTintColor = CXColor(189, 189, 189);
pageControl.centerX = scrollW * 0.5;
pageControl.centerY = scrollH - 50;
[self.view addSubview:pageControl];
self.pageControl = pageControl;
这是创建scrollview,并添加图片和设置属性的代码,接下来,要实现scrollview的代理方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
double page = scrollView.contentOffset.x / scrollView.width;
self.pageControl.currentPage = (int)(page + 0.5);
}
现在我们可以设置最后一个imageview上的点击按钮:
- (void)setupLastImageView:(UIImageView *)imageView
{
// 开启交互功能
imageView.userInteractionEnabled = YES;
// 马上进入
UIButton *startBtn = [[UIButton alloc] init];
[startBtn setBackgroundImage:[UIImage imageNamed:@"start_button"] forState:UIControlStateNormal];
[startBtn setBackgroundImage:[UIImage imageNamed:@"start_button_highlighted"] forState:UIControlStateHighlighted];
startBtn.centerX = imageView.width * 0.5;
startBtn.centerY = imageView.height * 0.75;
[startBtn setTitle:@"马上进入" forState:UIControlStateNormal];
[startBtn addTarget:self action:@selector(startClick) forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:startBtn];
}
最后,我们要进入主app,就是push进去或是model进去都不好,那我们怎么办呢?看下面:
- (void)startClick
{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
window.rootViewController = [[HWTabBarViewController alloc] init];
}
导览视图是不是so easy就完事了,接下来是显示它了,大家切换到AppDelgate.m文件,找到application:didFinishLaunchingWithOptions函数:
NSString *bundlekey = @"CFBundleVersion";
// 上一次的使用版本
NSString *lastVersion = [[NSUserDefaults standardUserDefaults] objectForKey:bundlekey];
// 当前软件的版本号
NSString *currentVersion = [NSBundle mainBundle].infoDictionary[bundlekey];
if ([currentVersion isEqualToString:lastVersion]) { // 版本相同:直接进入
self.window.rootViewController = [[HWTabBarViewController alloc] init];
} else { // 不同:进入导览
self.window.rootViewController = [[HWNewfeatureViewController alloc] init];
// 将当前的版本号存储
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:bundlekey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
好了,导览页的实现简单,想清楚实现就行。