本来是做 Android 开发、兼职 Unity 开发,公司有业务需求要做 iOS,还好需求比较简单:做一个 WebView + AR 的 App。WebView 感觉比较简单,AR 的话就用 EasyAR 吧,免费无水印值得推荐。
但是。。。
做完后要改需求,原因是有人告知**单纯的 WebView App 发布的时候审核不会通过。**为了不蹚浑水还是直接重做吧:首页是一个全屏 Banner,内容是日历加下方的图片,点击到 AR 页面扫描首页的图片可以看到视频。
作为一只程序猿要有各种东西都能做,各种代码都会码的觉悟,仗着有点代码基础(Java C#)就直接开搞。
##一. 准备工作
ios苹果开发者账号申请流程(2017)
最新的 iOS 申请证书与发布流程(2016.12)
##二. 基础知识
Objective C 基础知识 | 菜鸟教程
十分钟让你明白Objective-C的语法(和Java、C++的对比)
iOS8 App开发快速入门
下面这个就比较全面了,但是也有许多我没用上的知识。
iOS开发全套教程(享精品公开课)
所以综合一下,建议是不需要全部看完,根据项目需求来学习相关知识,毕竟先做出项目才是王道。
##三. HelloWorld
因为 EasyAR 提供 iOS 版本的示例代码,所以在现有的代码基础上进行二次开发,接下来根据项目需求来一步一步进行开发。
#####3.1 建立 WebView
第一版的 App 首页就是个 WebView,本小白刚开始做的时候直接在 Main.storyboard 里面拖放 UIWebView,现在看来是 Low 上加 Low…
首先来说,不建议在 storyboard 直接做事情,因为使用 storyboard 编程比较适合一个人开发,而且维护性不高。全部用代码则会显得一目了然,代码阅读性比较高。但是 storyboard 也有很多优势,同时有很多团队支持使用 storyboard 开发。所以我们要根据具体情况使用合适的方法来完成一个优雅的项目。
再者,UIWebView 是比较老的一个控件,而比较新的 WebView 控件则是 WKWebView,无论从内存占用和使用体验来说都优于 UIWebView。
下面是我找到使用简单,代码清晰,而且带前进后退和进度条的 WKWebView 使用实例,还有源码哦。使用的时候根据需求修改各个控件的位置和大小就可以了。
项目需求 WebView 上面需要一个标题栏,一个光秃秃的 WebView 确实也不甚好看,标题栏是一个简单的图片,用 UIImageView 就可以啦。
// 状态栏(statusbar)
CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
// 当前view的宽和高
CGFloat w = self.view.bounds.size.width;
CGFloat h = self.view.bounds.size.height;
// 添加title
UIImageView *titleImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, rectStatus.size.height, w, 60)];
[titleImage setImage:[UIImage imageNamed:@"ic_title"]];
[self.view addSubview:titleImage];
代码很好理解,首先获取手机状态栏的属性,因为它的高度需要用到。然后获取当前 App 显示区域的 View 的宽和高,最后添加标题栏的icon。短短的一段代码包含了很多信息:
OC 获取iOS屏幕尺寸大小
CGRectMake(0, rectStatus.size.height, w, 60)
iPhone开发中Cocoa中的CGRectMake具体用法
[titleImage setImage:[UIImage imageNamed:@"ic_title"]];
#####3.3 添加 UIButton 的点击和返回
上面的 titleBar 有左右两个按钮,左边的按钮用于跳转到当天时间的页面,右边的跳转到 AR 界面,没有美工啊…暂时先实现功能吧,按钮的点击响应什么的,以后再说。
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *todayButton = [[UIButton alloc] initWithFrame:CGRectMake(0, rectStatus.size.height, w*0.18, titleHeight)];
//设置按钮点击触发动作跳转
[todayButton addTarget:self action:@selector(goToday:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:todayButton];
UIButton *arButton = [[UIButton alloc] initWithFrame:CGRectMake(w-w*0.18, rectStatus.size.height, w*0.18, titleHeight)];
//设置按钮点击触发动作跳转
[arButton addTarget:self action:@selector(goAR:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:arButton];
}
- (void)goToday:(UIButton*) sender
{
...
}
- (void)goAR:(UIButton*) sender
{
// 实例化要跳转的 ViewController
ViewController *subView = [[ViewController alloc] init];
// 设置跳转动画类型
[subView setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
// 执行跳转
[self presentModalViewController:subView animated:YES];
}
代码比较简单,实例化两个按钮分别绑定不用的方法,goToday() 聊不到所以省略掉。goAR() 注释写的比较明白,这种跳转比较简单不需要 Navigationbar,而从 AR 界面跳转回来是这样的:
- (void)viewDidLoad {
[super viewDidLoad];
UIImage * buttonImage = [UIImage imageNamed:@"ic_back"];
self.backButton = [[UIButton alloc] initWithFrame:CGRectMake(20, 30, 30, 30)];
// 设置按钮的标题文字以及颜色
//[self.backButton setTitle:@"返回" forState:UIControlStateNormal];
//[self.backButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
// 设置按钮背景图
[self.backButton setImage:buttonImage forState:UIControlStateNormal];
//设置按钮点击触发动作跳转
[self.backButton addTarget:self action:@selector(backToView:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.backButton];
}
- (void) backToView:(UIButton*) sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
与其说是跳转回来,不如说是把当前的 View 隐藏更为贴切,更多关于界面跳转可以参考下文或自行度娘:
iOS ViewController跳转界面的几种方法简单总结
#####3.4 iOS 消息传递与小菊花
需求:扫描识别到图片之后要播放视频,但是视频文件比较大,所以在识别到图片的时候开始旋转小菊花并在线缓存视频,开始播放视频或者离开识别图隐藏小菊花。
找到的资料是这样的:
IOS中消息传递的8种方式
Class B 发现识别图开始发送消息
- (void)onFound
{
// 发现识别图发送消息显示并播放小菊花动画
[[NSNotificationCenter defaultCenter] postNotificationName:@"showIndicator" object:nil];
if (prepared) {
// 视频马上就要播放,隐藏小菊花动画
[[NSNotificationCenter defaultCenter] postNotificationName:@"closeIndicator" object:nil];
}
}
Class A 设置监听并根据发来的消息展示和隐藏小菊花
- (void)viewDidLoad {
// 注册观察者显示
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showIndicator) name:@"showIndicator" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeIndicator) name:@"closeIndicator" object:nil];
}
//接受消息显示小菊花
- (void)showIndicator
{
dispatch_async(dispatch_get_main_queue(), ^{
//do your UI
[self.activityIndicator startAnimating];
self.textView.text = @"Loading...";
});
}
//接受消息关闭小菊花
- (void)closeIndicator
{
dispatch_async(dispatch_get_main_queue(), ^{
//do your UI
[self.activityIndicator stopAnimating];
self.textView.text = @"";
});
}
为求方便直接注册监听两个方法,其实更好的写法是只监听一个方法,Class B 发送 Notification 时带参数,Class A 根据不同参数作不同的处理。
iOS NSNotification 消息通知的3种方式
// 创建全局变量
@property (strong, nonatomic) UIActivityIndicatorView *activityIndicator;
- (void)viewDidLoad {
// 小菊花设置
self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleWhiteLarge)];
// 这个是用来设置小菊花的中心点,很多 View 也可以设置
self.activityIndicator.center = CGPointMake(width/2,height/2-40);
}
// 显示小菊花
[self.activityIndicator startAnimating];
// 隐藏小菊花
[self.activityIndicator stopAnimating];
自定义外观和更多使用方式可以参考文章:
iOS UIActivityIndicatorView用法(菊花旋转)
#####3.5 CocoaPods 以及第三方库的使用
主要功能和 WebView 做好之后要改需求,原因上文已经提到过,接下来要做一个全屏滑动、内容为 2018 年日历的 Banner,以及根据当前的日期跳转到指定的日历页面,用下面的代码获取日期后跳转到 Banner 的某一页就可以了。
//获取当前时间日期并返回 int
- (int)getDate:(NSString *)dateType{
NSDate *date=[NSDate date];
NSDateFormatter *format1=[[NSDateFormatter alloc] init];
if([dateType isEqualToString:@"mouth"]){
[format1 setDateFormat:@"MM"];
}else if([dateType isEqualToString:@"day"]){
[format1 setDateFormat:@"dd"];
}else{
[format1 setDateFormat:@"MMdd"];
}
// @"yyyy-MM-dd hh:mm:ss"
NSString *dateStr = [format1 stringFromDate:date];
return [dateStr intValue];
}
// 获取日期并返回 NSString。可以返回具体周几
- (NSString*) getAllDate{
NSDate*date = [NSDate date];
NSCalendar*calendar = [NSCalendar currentCalendar];
NSDateComponents*comps;
comps =[calendar components:(NSCalendarUnitWeekOfYear | NSCalendarUnitWeekday |NSCalendarUnitWeekdayOrdinal)
fromDate:date];
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init] ;
// [dateFormatter setDateFormat:@"YYYY-MM-dd EEEE"];
[dateFormatter setDateFormat:@"MMM dd YYYY"];
NSString *currentTimeString = [dateFormatter stringFromDate:date];
return currentTimeString;
}
然后就是 Banner 了,让我自己去写这样一个 Banner 是不太可能的,首先技术不到家而且也没啥时间去慢慢研究着写,所以使用第三方库是最合适的。于是在 GayHub 找各种 Banner 库,发现大家都在用 Pod 导入。
查了下发现 Pod 是用来导入第三方库的工具,全称 CocoaPods。虽然直接下载Library 放到项目里可以用但是保不齐第三方库又引用了其它库,难道都要一个一个 Copy 进项目?况且这种东西向来是学了不亏而且以后做 iOS 开发总要用到的,所以还是老老实实学着怎么安装和使用吧。
安装 CocoaPods 之前需要先安装 Ruby 运行环境,然后才能命令行安装 CocoaPods:
Ruby运行环境:如何在Mac OS X上安装 Ruby运行环境
接下来参考下文来安装 CocoaPods
CocoaPods:看一遍就会的CocoaPods的安装和使用教程
安装过程中可能会报各种各样的错误,不要着急,参考下方资料。如果资料不能解决你的问题,Google 或 度娘 你的报错Log。
最详细的CocoaPods安装教程附常见错误总结
安装完毕就可以使用 CocoaPods 了,多去 GayHub 转转,总有各种各样的惊喜等着你。
#####3.6 其它问题
//设置状态栏字体样式
- (UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;//白色
}
##四. App 发布
这里有一个很详细的教程:
iOS App上架流程(2016详细版)
跟着教程一步一步做终于是把 App 扔上去审核了,感觉比较难找的就是 iTunesConnect 放个链接标记一下。
到这里就完成了项目需求。文中引用了各种连接,就不一一提示引用了,感谢那么多前辈的无私分享,也祝大家都能完成一个完美的 App。
上架过程中遇到的各种问题:
本来是做 Android 开发、兼职 Unity 开发,公司有业务需求要做 iOS,还好需求比较简单:做一个 WebView + AR 的 App。WebView 感觉比较简单,AR 的话就用 EasyAR 吧,免费无水印值得推荐。
但是。。。
做完后要改需求,原因是有人告知**单纯的 WebView App 发布的时候审核不会通过。**为了不蹚浑水还是直接重做吧:首页是一个全屏 Banner,内容是日历加下方的图片,点击到 AR 页面扫描首页的图片可以看到视频。
作为一只程序猿要有各种东西都能做,各种代码都会码的觉悟,仗着有点代码基础(Java C#)就直接开搞。
##一. 准备工作
ios苹果开发者账号申请流程(2017)
最新的 iOS 申请证书与发布流程(2016.12)
##二. 基础知识
Objective C 基础知识 | 菜鸟教程
十分钟让你明白Objective-C的语法(和Java、C++的对比)
iOS8 App开发快速入门
下面这个就比较全面了,但是也有许多我没用上的知识。
iOS开发全套教程(享精品公开课)
所以综合一下,建议是不需要全部看完,根据项目需求来学习相关知识,毕竟先做出项目才是王道。
##三. HelloWorld
因为 EasyAR 提供 iOS 版本的示例代码,所以在现有的代码基础上进行二次开发,接下来根据项目需求来一步一步进行开发。
#####3.1 建立 WebView
第一版的 App 首页就是个 WebView,本小白刚开始做的时候直接在 Main.storyboard 里面拖放 UIWebView,现在看来是 Low 上加 Low…
首先来说,不建议在 storyboard 直接做事情,因为使用 storyboard 编程比较适合一个人开发,而且维护性不高。全部用代码则会显得一目了然,代码阅读性比较高。但是 storyboard 也有很多优势,同时有很多团队支持使用 storyboard 开发。所以我们要根据具体情况使用合适的方法来完成一个优雅的项目。
再者,UIWebView 是比较老的一个控件,而比较新的 WebView 控件则是 WKWebView,无论从内存占用和使用体验来说都优于 UIWebView。
下面是我找到使用简单,代码清晰,而且带前进后退和进度条的 WKWebView 使用实例,还有源码哦。使用的时候根据需求修改各个控件的位置和大小就可以了。
项目需求 WebView 上面需要一个标题栏,一个光秃秃的 WebView 确实也不甚好看,标题栏是一个简单的图片,用 UIImageView 就可以啦。
// 状态栏(statusbar)
CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
// 当前view的宽和高
CGFloat w = self.view.bounds.size.width;
CGFloat h = self.view.bounds.size.height;
// 添加title
UIImageView *titleImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, rectStatus.size.height, w, 60)];
[titleImage setImage:[UIImage imageNamed:@"ic_title"]];
[self.view addSubview:titleImage];
代码很好理解,首先获取手机状态栏的属性,因为它的高度需要用到。然后获取当前 App 显示区域的 View 的宽和高,最后添加标题栏的icon。短短的一段代码包含了很多信息:
OC 获取iOS屏幕尺寸大小
CGRectMake(0, rectStatus.size.height, w, 60)
iPhone开发中Cocoa中的CGRectMake具体用法
[titleImage setImage:[UIImage imageNamed:@"ic_title"]];
#####3.3 添加 UIButton 的点击和返回
上面的 titleBar 有左右两个按钮,左边的按钮用于跳转到当天时间的页面,右边的跳转到 AR 界面,没有美工啊…暂时先实现功能吧,按钮的点击响应什么的,以后再说。
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *todayButton = [[UIButton alloc] initWithFrame:CGRectMake(0, rectStatus.size.height, w*0.18, titleHeight)];
//设置按钮点击触发动作跳转
[todayButton addTarget:self action:@selector(goToday:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:todayButton];
UIButton *arButton = [[UIButton alloc] initWithFrame:CGRectMake(w-w*0.18, rectStatus.size.height, w*0.18, titleHeight)];
//设置按钮点击触发动作跳转
[arButton addTarget:self action:@selector(goAR:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:arButton];
}
- (void)goToday:(UIButton*) sender
{
...
}
- (void)goAR:(UIButton*) sender
{
// 实例化要跳转的 ViewController
ViewController *subView = [[ViewController alloc] init];
// 设置跳转动画类型
[subView setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
// 执行跳转
[self presentModalViewController:subView animated:YES];
}
代码比较简单,实例化两个按钮分别绑定不用的方法,goToday() 聊不到所以省略掉。goAR() 注释写的比较明白,这种跳转比较简单不需要 Navigationbar,而从 AR 界面跳转回来是这样的:
- (void)viewDidLoad {
[super viewDidLoad];
UIImage * buttonImage = [UIImage imageNamed:@"ic_back"];
self.backButton = [[UIButton alloc] initWithFrame:CGRectMake(20, 30, 30, 30)];
// 设置按钮的标题文字以及颜色
//[self.backButton setTitle:@"返回" forState:UIControlStateNormal];
//[self.backButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
// 设置按钮背景图
[self.backButton setImage:buttonImage forState:UIControlStateNormal];
//设置按钮点击触发动作跳转
[self.backButton addTarget:self action:@selector(backToView:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.backButton];
}
- (void) backToView:(UIButton*) sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
与其说是跳转回来,不如说是把当前的 View 隐藏更为贴切,更多关于界面跳转可以参考下文或自行度娘:
iOS ViewController跳转界面的几种方法简单总结
#####3.4 iOS 消息传递与小菊花
需求:扫描识别到图片之后要播放视频,但是视频文件比较大,所以在识别到图片的时候开始旋转小菊花并在线缓存视频,开始播放视频或者离开识别图隐藏小菊花。
找到的资料是这样的:
IOS中消息传递的8种方式
Class B 发现识别图开始发送消息
- (void)onFound
{
// 发现识别图发送消息显示并播放小菊花动画
[[NSNotificationCenter defaultCenter] postNotificationName:@"showIndicator" object:nil];
if (prepared) {
// 视频马上就要播放,隐藏小菊花动画
[[NSNotificationCenter defaultCenter] postNotificationName:@"closeIndicator" object:nil];
}
}
Class A 设置监听并根据发来的消息展示和隐藏小菊花
- (void)viewDidLoad {
// 注册观察者显示
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showIndicator) name:@"showIndicator" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeIndicator) name:@"closeIndicator" object:nil];
}
//接受消息显示小菊花
- (void)showIndicator
{
dispatch_async(dispatch_get_main_queue(), ^{
//do your UI
[self.activityIndicator startAnimating];
self.textView.text = @"Loading...";
});
}
//接受消息关闭小菊花
- (void)closeIndicator
{
dispatch_async(dispatch_get_main_queue(), ^{
//do your UI
[self.activityIndicator stopAnimating];
self.textView.text = @"";
});
}
为求方便直接注册监听两个方法,其实更好的写法是只监听一个方法,Class B 发送 Notification 时带参数,Class A 根据不同参数作不同的处理。
iOS NSNotification 消息通知的3种方式
// 创建全局变量
@property (strong, nonatomic) UIActivityIndicatorView *activityIndicator;
- (void)viewDidLoad {
// 小菊花设置
self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleWhiteLarge)];
// 这个是用来设置小菊花的中心点,很多 View 也可以设置
self.activityIndicator.center = CGPointMake(width/2,height/2-40);
}
// 显示小菊花
[self.activityIndicator startAnimating];
// 隐藏小菊花
[self.activityIndicator stopAnimating];
自定义外观和更多使用方式可以参考文章:
iOS UIActivityIndicatorView用法(菊花旋转)
#####3.5 CocoaPods 以及第三方库的使用
主要功能和 WebView 做好之后要改需求,原因上文已经提到过,接下来要做一个全屏滑动、内容为 2018 年日历的 Banner,以及根据当前的日期跳转到指定的日历页面,用下面的代码获取日期后跳转到 Banner 的某一页就可以了。
//获取当前时间日期并返回 int
- (int)getDate:(NSString *)dateType{
NSDate *date=[NSDate date];
NSDateFormatter *format1=[[NSDateFormatter alloc] init];
if([dateType isEqualToString:@"mouth"]){
[format1 setDateFormat:@"MM"];
}else if([dateType isEqualToString:@"day"]){
[format1 setDateFormat:@"dd"];
}else{
[format1 setDateFormat:@"MMdd"];
}
// @"yyyy-MM-dd hh:mm:ss"
NSString *dateStr = [format1 stringFromDate:date];
return [dateStr intValue];
}
// 获取日期并返回 NSString。可以返回具体周几
- (NSString*) getAllDate{
NSDate*date = [NSDate date];
NSCalendar*calendar = [NSCalendar currentCalendar];
NSDateComponents*comps;
comps =[calendar components:(NSCalendarUnitWeekOfYear | NSCalendarUnitWeekday |NSCalendarUnitWeekdayOrdinal)
fromDate:date];
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init] ;
// [dateFormatter setDateFormat:@"YYYY-MM-dd EEEE"];
[dateFormatter setDateFormat:@"MMM dd YYYY"];
NSString *currentTimeString = [dateFormatter stringFromDate:date];
return currentTimeString;
}
然后就是 Banner 了,让我自己去写这样一个 Banner 是不太可能的,首先技术不到家而且也没啥时间去慢慢研究着写,所以使用第三方库是最合适的。于是在 GayHub 找各种 Banner 库,发现大家都在用 Pod 导入。
查了下发现 Pod 是用来导入第三方库的工具,全称 CocoaPods。虽然直接下载Library 放到项目里可以用但是保不齐第三方库又引用了其它库,难道都要一个一个 Copy 进项目?况且这种东西向来是学了不亏而且以后做 iOS 开发总要用到的,所以还是老老实实学着怎么安装和使用吧。
安装 CocoaPods 之前需要先安装 Ruby 运行环境,然后才能命令行安装 CocoaPods:
Ruby运行环境:如何在Mac OS X上安装 Ruby运行环境
接下来参考下文来安装 CocoaPods
CocoaPods:看一遍就会的CocoaPods的安装和使用教程
安装过程中可能会报各种各样的错误,不要着急,参考下方资料。如果资料不能解决你的问题,Google 或 度娘 你的报错Log。
最详细的CocoaPods安装教程附常见错误总结
安装完毕就可以使用 CocoaPods 了,多去 GayHub 转转,总有各种各样的惊喜等着你。
#####3.6 其它问题
//设置状态栏字体样式
- (UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;//白色
}
##四. App 发布
这里有一个很详细的教程:
iOS App上架流程(2016详细版)
跟着教程一步一步做终于是把 App 扔上去审核了,感觉比较难找的就是 iTunesConnect 放个链接标记一下。
到这里就完成了项目需求。文中引用了各种连接,就不一一提示引用了,感谢那么多前辈的无私分享,也祝大家都能完成一个完美的 App。
上架过程中遇到的各种问题: