iOS7最佳实践:一个天气App案例
注:本文译自: raywenderlich ios-7-best-practices-part-1 ,去除了跟主题无关的寒暄部分。 欢迎转载,保持署名
在这个两部分的系列教程中,您将探索如何使用以下工具和技术来创建自己的App:
- Cocoapods
- Manual layout in code(纯代码布局)
- ReactiveCocoa
- OpenWeatherMap
本教程专为熟悉基本知识的、但还没有接触到太多高级主题的中级开发者而设计。本教程也是想要去探索Objective-C 函数编程 一个很好的开始。
开始
打开Xcode并执行 File\New\Project
。选择Application\Empty Application
。将项目命名为 SimpleWeather
,单击下一步,选择一个目录去保存你的项目,然后点击Create。 现在,你的基础项目已经完成。下一步是集成你的第三方工具。但首先你要 关闭Xcode
,确保他不会影响下一步。
Cocoapods
你将要下载 Cocoapods 的代码,在Xcode项目中添加文件来使用,并配置项目需要的设置。
Mantle
Mantle 是由于Github团队开发的,目的是去除Objective-C把JSON数据转为NSObject子类的所有样板代码。Mantle也能做数据转换,通过一种神奇的方式把JSON原始数据(strings, ints, floats)转换为复杂数据,比如NSDate, NSURL, 甚至是自定义类。
LBBlurredImage
LBBlurredImage 是一个继承自UIImageView,轻而易举使图像模糊的项目。你将仅仅用一行代码来创建一个神奇的模糊效果。
TSMessages
TSMessages 是另一个非常简单的库,用来显示浮层警告和通知。当出现错误信息而不直接影响用户的时候,最好使用浮层来代替模态窗口(例如UIAlertView),这样你将尽可能减少对用户的影响。
你将只用TSMessages,在网络失去连接或API错误的时候。如果发生错误,你将看到类似这样的一个浮层:
ReactiveCocoa
最后,你将使用到 ReactiveCocoa ,他也来自于GitHub团队。ReactiveCocoa给Objective-C带来了函数编程,类似与.NET的 Reactive Extensions 。你将在第二部分花费大部分时间去实现ReactiveCocoa。
设置你的Cocoapods
设置你的Cocoapods,先要确保你已经安装了Cocoapods。为此,打开命令行程序,并输入。
1 |
|
你将会看到类似这样的输出:
1 |
|
这决定于你如何管理Ruby gems,例如你使用 rbenv 或 RVM ,路径可能有所不同。
如果命令行简单的返回提示,或显示 pod not found
,表示Cocoapods未安装在你的机器上。可以查看我们的 Cocoapods教程 作为安装说明。这也是一个很好的资源,如果你想更多得了解Cocoapods的话。
Podfiles 是用来告诉Cocoapods哪些开源项目需要导入。
要创建你的第一个Cocoapod,首先在命令行中用 cd
命令导航到你的XCode项目所在的文件夹,在命令行中启动编辑器,输入
1 2 3 4 5 6 |
|
这文件做了两件事情:
- 告诉Cocoapods你的目标平台与版本,这里的你目标是iOS 7.0。
- 列给Cocoapods一个项目所有需要引入和安装的三方库清单。
在命令行中输入 pod install
进行安装。
这可能需要花一到两分钟的时间去安装各种包。你的命令行应该输出如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 |
|
Cocoapods会在你的项目目录中创建一堆新文件,但是,只有一个需要你关心,SimpleWeather.xcworkspace
。
用Xcode打开 SimpleWeather.xcworkspace
。看看你的项目设置,现在有一个Pods项目在你的项目工作区,以及在Pods文件夹放着每一个你引入的库,如下所示:
确保你已经选择SimpleWeather项目,如图所示:
构建并运行您的App,以确保一切工作正常:
1 |
|
创建你的主视图控制器
虽然这个App看起来复杂,但它还会通过一个单一的View Controller完成。现在,你将添加他。
选中 SimpleWeather
项目,单击 File\New\File
,并且选择Cocoa Touch\Objective-C class
. 命名为 WXController
,并设置为UIViewController
的子类。
确保 Targeted for iPad
和 With XIB for user interface
都没有选中,如下图所示:
打开 WXController.m
然后用如下所示替换 -viewDidLoad
方法:
1 2 3 4 5 6 |
|
现在打开 AppDelegate.m
,并且引入如下两个class:
1 2 |
|
眼尖的读者会注意到 WXController
使用引号引入, TSMessage
使用单括号引入。
回头看下当你创建Podfile的时候,你使用Cocoapods引入 TSMessage
。Cocoapods创建TSMessage项目,并把它加入到工作空间。既然你从工作区的其他项目导入,可以使用尖括号代替引号。
代替 -application:didFinishLaunchingWithOptions
的内容:
1 2 3 4 5 6 7 8 9 10 |
|
标号注释的解释:
- 初始化并设置
WXController
实例作为App的根视图控制器。通常这个控制器是一个的UINavigationController
或UITabBarController
,但在当前情况下,你使用WXController
的单个实例。 - 设置默认的视图控制器来显示你的TSMessages。这样做,你将不再需要手动指定要使用的控制器来显示警告。
构建并运行,看看你的新视图控制器起作用了。
在红色背景下,状态栏有点不够清晰。幸运的是,有一个简单的方法,使状态栏更清晰易读。
在iOS7, UIViewController 有一个新的API,用来控制状态栏的外观。打开WXController
,直接添加下面的代码到 -viewDidLoad:
方法下:
1 2 3 |
|
再次构建并运行,你将看到状态栏如下的变化:
设置你的App视图
现在是时候让你的App接近生活。下载这个项目的 图片 ,并解压缩到一个合适的位置。这个压缩包的背景图片出自Flickr用户 idleformat 之手,天气图片出自Dribbble用户 heeyeun 之手。
切换回Xcode,单击 File\Add Files to “SimpleWeather”
….定位到你刚刚解压缩的图片文件夹并选择它。选择Copy items into destination group’s folder (if needed)
,然后单击 Add
。
打开 WXController.h
, 添加如下委托协议:
1 |
|
现在打开 WXController.m
。 小提示:你可以使用 Control-Command-Up
的快捷键来实现 .h
和 .m
文件之间的快速切换。
添加如下代码到 WXController.m
顶部:
1 |
|
LBBlurredImage.h
包含在Cocoapods引入的 LBBlurredImage
项目,你会使用这个库来模糊背景图片。
应该有一个空的私有接口样板在 WXController
imports的下方。它具有以下属性:
1 2 3 4 5 6 7 8 |
|
现在,是时候在项目中创建并设置视图。
下面是你App的分解图,记住,table view将是透明的:
为了实现动态模糊效果,在你的App中,你会根据App的滚动来改变模糊图像的alpha值。
打开 WXController.m
,使用如下代码来,替换掉 -viewDidLoad
中设置背景色的代码:
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 |
|
这是非常简单的代码:
- 获取并存储屏幕高度。之后,你将在用分页的方式来显示所有天气 数据时,使用它。
- 创建一个静态的背景图,并添加到视图上。
- 使用LBBlurredImage来创建一个模糊的背景图像,并设置alpha为0,使得开始
backgroundImageView
是可见的。 - 创建tableview来处理所有的数据呈现。 设置WXController为delegate和dataSource,以及滚动视图的delegate。请注意,设置
pagingEnabled
为YES
。
添加如下UITableView的delegate和dataSource的代码到 WXController.m
的@implementation
块中:
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 29 30 31 32 33 34 35 36 37 38 |
|
Pragma mark
是 组织代码 的很好的一种方式。- 你的table view有两个部分,一个是每小时的天气预报,另一个用于每日播报。table view的section数目,设置为2。
- 天气预报的cell是不可选择的。给他们一个半透明的黑色背景和白色文字。
1 |
|
最后,添加如下代码到 WXController.m
:
1 2 3 4 5 6 7 8 9 |
|
在 WXController.m
中,你的视图控制器调用该方法来编排其子视图。
构建并运行你的App,看看你的视图如何堆叠。
仔细看,你会看到所有空的table cell的cell分隔线。
仍然在 -viewDidLoad
中,添加下面的代码来设置你的布局框架和边距:
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 |
|
这是相当常规设置代码,但这里是怎么回事:
- 设置table的header大小与屏幕相同。你将利用的UITableView的分页来分隔页面页头和每日每时的天气预报部分。
- 创建inset(或padding)变量,以便您的所有标签均匀分布并居中。
- 创建并初始化为各种视图创建的高度变量。设置这些值作为常量,使得可以很容易地在需要的时候,配置和更改您的视图设置。
- 使用常量和inset变量,为label和view创建框架。
- 复制图标框,调整它,使文本具有一定的扩展空间,并将其移动到该图标的右侧。当我们把标签添加到视图,你会看到布局的效果。
添加如下代码到 -viewDidLoad
:
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
这是相当长的一块代码,但它真的只是在做设置各种控件的繁重工作。简单的说:
- 设置当前view为你的table header。
- 构建每一个显示气象数据的标签。
- 添加一个天气图标的图像视图。
构建并运行你的App,你应该可以看到你之前布局的所有所有view。下面的屏幕截图显示了使用手工布局的、所有标签框在视觉上的显示。
用手指轻轻推动table,当你滚动它的时候,应该会反弹。
获取气象数据
你会注意到,App显示“Loading…”,但它不是真正地在工作。是时候获取一些真正的天气数据。
你会从 OpenWeatherMap 的API拉取数据。 OpenWeatherMap是一个非常棒的服务,旨在提供实时,准确,免费的天气数据给任何人。虽然有很多天气API,但他们大多要么使用较旧的数据格式,如XML,或是有偿服务 – 并且有时还相当昂贵。
你会遵循以下基本步骤,来获你设备的位置的气象数据:
- 找到设备的位置
- 从 API端 下载JSON数据
- 映射JSON到
WXConditions
和WXDailyForecasts
- 告诉UI有新数据了
开始创建你的天气模型和数据管理类。单击 File\New\File…
并选择Cocoa Touch\Objective-C class
。命名为 WXClient
并使其为NSObject
的子类。
这样再做三次创建以下类:
WXManager
作为NSObject
的子类WXCondition
作为MTLModel
的子类WXDailyForecast
作为WXCondition
的子类
全部完成?现在,你可以开始下一节,其中涉及映射和转换您的天气数据。
创建你的天气模型
你的模型将使用 Mantle ,这使得数据映射和转型非常简单。
打开 WXCondition.h
如下列代码,修改接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
MTLJSONSerializing
协议告诉Mantle序列化该对象如何从JSON映射到Objective-C的属性。- 这些都是你的天气数据的属性。你将会使用这些属性的get set方法,但是当你要扩展App,这是一种很好的方法来访问数据。
- 这是一个简单的辅助方法,从天气状况映射到图像文件。
构建并运行App。失败了……
原因是你没有从你的Cocoapods项目中引入 Mantle
。解决方法是,在WXCondition.h
中,你需要把 MTLModel.h
替换为 #import <Mantle.h>
。
现在构建并运行App。成功了。你会看到一些新的警告,但你可以忽略他们。
首先,你需要处理未实现的 -imageName
方法。
打开 WXCondition.m
,添加如下方法:
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 29 30 31 32 33 |
|
- 创建一个静态的NSDictionary,因为WXCondition的每个实例都将使用相同的数据映射。
- 天气状况与图像文件的关系(例如“01d”代表“weather-clear.png”)。
- 声明获取图像文件名的公有方法。
看一看从OpenWeatherMap返回的JSON响应数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
你需要把嵌套的JSON值映射到Objective-C的属性。嵌套的JSON值是元素,如温度,即上面看到的 main
节点。
要做到这一点,你将利用的Objective-C的 Key-Value Coding 和Mantle 的MTLJSONAdapter 。
还在 WXCondition.m
,通过添加 +JSONKeyPathsByPropertyKey
方法,“JSON到模型属性”的映射,且该方法是 MTLJSONSerializing
协议的require 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
在这个方法里,dictionary的key是 WXCondition
的属性名称,而dictionary的value是JSON的路径。
您可能已经注意到,这里有一个从JSON数据映射到Objective-C属性的问题。属性date
是 NSDate
类型的,但JSON有一个Unix时间类型(sjpsega注:即从1970年1月1日0时0分0秒起至现在的总秒数)的NSInteger值。你需要完成两者之间的转换。
Mantle正好有一个功能来为你解决这个问题: MTLValueTransformer 。这个类允许你声明一个block,详细说明值的相互转换。
Mantle的转换器语法有点怪。要创建一个为一个特定属性的转换器,,您可以添加一个以属性名开头和 JSONTransformer
结尾的类方法。 可能看实际代码比试图解释它更容易理解,所以在 WXCondition.m
中添加以下为NSDate属性设置的转换器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
- 使用blocks做属性的转换的工作,并返回一个MTLValueTransformer返回值。
- 您只需要详细说明Unix时间和NSDate之间进行转换一次,就可以重用
-dateJSONTransformer
方法为sunrise和sunset属性做转换。
下一个值转型有点讨厌,但它只是使用OpenWeatherMap的API,并自己的格式化JSON响应方式的结果。 weather
键对应的值是一个JSON数组,但你只关注单一的天气状况。
在 WXCondition.m
中,使用 dateJSONTransformer
相同的结构,您可以创建一个NSArray和NSString的之间的转换。该解决方案提供如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
最后的转换器只是为了格式化。 OpenWeatherAPI使用每秒/米的风速。由于您的App使用英制系统,你需要将其转换为每小时/英里。
在 WXCondition.m
的实现中添加以下转换器的方法和宏定义。
1 2 3 4 5 6 7 8 9 |
|
在OpenWeatherMap的API中有一个小的差异,你必须处理。看一看在位于 当前状况的响应 和 每日预测反应 之间的温度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
current
的第一个key是 main
,最高温度存储在key temp_max
中,而daily forecast
的第一个key是 temp
,最高温度存储在key max
中。
key Temperature的差异放在一边,其他都一样。所以,你真正需要做的是修改daily forecasts的键映射。
打开 WXDailyForecast.m
重写 +JSONKeyPathsByPropertyKey
方法:
1 2 3 4 5 6 7 8 9 |
|
- 获取
WXCondition
的映射,并创建它的可变副本。 - 你需要为daily forecast做的是改变max和min键映射。
- 返回新的映射。
构建并运行您的App,看起来和上次运行没什么改变,但好的一点是,App编译和运行没有任何错误。
何去何从?
你可以从 这里 下载完整程序。
在这部分教程中,您使用Cocoapods设置项目,增加视图到控制器,编排视图,并建立模型来反映你抓取的气象数据。该App还没有充分发挥作用,但是你成功用纯代码创建视图,并学习了如何使用Mantle映射和转换JSON数据。
接下来看看教程的第二部分,你将充实你的App,从weather API获取数据,并在UI上显示。您将使用新的iOS7 NSURLSession 去下载数据,以及使用ReactiveCocoa
把位置查找,天气数据抓取和UI更新事件绑在一起。
iOS7最佳实践:一个天气App案例相关推荐
- iOS 7最佳实践:一个天气App案例
转自:sjpsega's Blog iOS7最佳实践:一个天气App案例(一) iOS7最佳实践:一个天气App案例(二) 注:本文译自:raywenderlich ios-7-best-practi ...
- iOS 7 最佳实践;一个天气应用: Part 1/2
为什么80%的码农都做不了架构师?>>> 每个开发者都有他们自己开发一个应用的好方法?一些开发者使用Auto-Layout,一些开发者使用图标算法,甚至一些开发者喜欢用Vim编 ...
- 一个天气App案例(一)
2019独角兽企业重金招聘Python工程师标准>>> 原文:raywenderlich ios-7-best-practices-part-1 翻译:http://www.coco ...
- 开源一个天气APP Build with React Native
About Github 断断续续花了几天的时间,利用网上开放的小米天气接口,基于React native 写了一个天气APP.App store 在审核中.设计能力有限,天气动画只加了两个,AE导出 ...
- flutter天气_牛笔!自己用Flutter撸一个天气APP
这是一款简约风格的 flutter 天气项目,提供实时.多日.24 小时.台风路径以及生活指数等服务,支持定位.删除.搜索等操作. 下图为主页效果: 开始 本身作为天气 APP,自定义绘制自然少不了, ...
- 用android制作一个记事本app_用扁平化呈现一个天气APP
作为当下最火的设计风格之一,扁平化设计其实是一种简约的Ul 设计理念,现被广泛应用于图形用户界面上,在图形材料,例如海报,艺术作品,指导文档,各类出版物等方面尤为常用. 今天为大家带来了我最近的扁平 ...
- flutter offset_牛笔!自己用Flutter撸一个天气APP
这是一款简约风格的 flutter 天气项目,提供实时.多日.24 小时.台风路径以及生活指数等服务,支持定位.删除.搜索等操作. 下图为主页效果: 开始 本身作为天气 APP,自定义绘制自然少不了, ...
- 碎片的最佳实践——一个简易版的新闻应用
现在你已经将关于碎片的重要知识点都掌握得差不多了,不过在灵活运用方面可能还有些欠缺,因此又该进入最佳实践环节了. 前面有提到过,碎片很多时候都是在平板开发当中使用的,主要是为了解决屏幕空间不能充分利用 ...
- Go语言 闭包的最佳实践 (Golang经典编程案例)
闭包:一个函数和与其相关的引用环境组合的一个整体. 最佳实践:编写一个程序,具体要求如下: 编写一个函数 makeSuffix(suffix string) ,可以接收一个文件后缀名(比如.jpg), ...
最新文章
- ACMNO.10打印出所有水仙花数,所谓水仙花数是指一个三位数,其各位数字立方和等于该本身。 例如:153是一个水仙花数,因为153=1^3+5^3+3^3。 Output: 153 ???
- 从0实现一个tinyredux
- matlab多元回归程序,多元回归程序MATLAB程序
- 一个Java对象到底占用多大内存?
- SAP中国际贸易条款的含义
- docker 镜像 导入导出
- C语言基础专题 - 通过案例历学 - 结构体
- 从工程师到架构师,Android程序员的进阶之路
- 物 理 学 简 介(三)
- 蓝桥杯-决赛A组第九届java
- 谷歌发布深度学习Efficient Net新架构,各方面表现全面碾压卷积神经网络
- 幻梦一场:Vulcan Project
- 猿如意中的【取色器】效率工具详情介绍
- Latex编辑器Texstudio的注释快捷键。
- 【计算机毕业设计】015健身房管理系统设计与实现
- AWS 亚马逊云良好架构框架
- 六年安卓开发的技术回顾和展望
- 批量文件压缩下载(zip)
- 分组统计group by
- 为什么 FIQ 比 IRQ 的响应速度更快?
热门文章
- 蓝奏云第三方cmd客户端(LanZouCloud-CMD)Cookie内容设置方法
- 张一鸣王欣罗永浩组团“围剿”微信 但马化腾却很放心
- 德国IT行业薪酬2019年终大盘点
- 到底该用GMT+8还是GMT-8?
- GMT6.1.1安装流程
- 《Effective C++》读书笔之六 Item 6. Explicitly disallow the use of compile-generated functions
- 中文版Postma以及Post请求显示“need_login“未登录解决方法
- win10安装GPU版tensorflow
- 中国IC设计公司2006年
- Android定制Home,以及launcher的自定义