毕业设计--天气预报App
9月中旬,开始动手做我的毕业设计了,之前一直在纠结做啥,后来想想,既然是做毕业设计,那就大胆地做点自己没接触过的东西吧。然后网上查找资料得知做天气预报需要用到开放的API,而且要用那种现在还在维护的,而且又免费的(对于我们学生党来说,这个是挺好的)。天气预报App的核心是从天气API请求数据,请求得到的一般是JSON数据(这个JSON数据之前都没接触过),然后把JSON数据解析,然后在视图上显示出来。总得来说,这里应该涉及到“网络请求”,“JSON解析”这两个大块吧,正好用来学习新的东西,并且练练手,于是就决定做个天气预报的App了。
- 第一步,找天气API
各种百度,然后找到了比较新的网站,分别是“心知天气”和“和风天气”。都需要注册,注册之后会得到一个key,用来进行数据请求的。两个网站都有付费和免费的两种选择,如图,比较完之后,二话不说,选择了和风天气的API。
- 第二步,找解析JSON的第三方框架
各种百度之后也找到了大家推荐的一些,如:JSONKit、Mantle、AFNetworking、SBJSON、MJExtension等等等等。。。最后参考一篇教程,还是选择了Mantle,当然不是说其他不好用,个人喜好而已。
Mantle的使用也很简单。
1、新建一个继承自MTLModel的类,并让他遵循<MTLJSONSerializing>协议,注意这里还要#import <MTLModel.h>
2、在.h文件定义你的模型,如:#import <Mantle/Mantle.h>
#import <MTLModel.h> @interface TSCondition : MTLModel<MTLJSONSerializing> @property (nonatomic, strong) NSString *cityName; // 城市名字
@property (nonatomic, strong) NSString *nowCond; // 当前天气状况
@property (nonatomic, strong) NSString *nowTmp; // 当前温度
@property (nonatomic, strong) NSString *winddir; // 风向
@property (nonatomic, strong) NSString *windsc; // 风力
@property (nonatomic, strong) NSString *date; // 日期
@property (nonatomic, strong) NSString *maxTmp; // 最高温度
@property (nonatomic, strong) NSString *minTmp; // 最低温度
@property (nonatomic, strong) NSString *weatherqlty; // 空气质量 @end3、在.m文件中实现类方法,实现JSON数据到模型的映射
+ (NSDictionary *)JSONKeyPathsByPropertyKey
{
return @{
@"cityName": @"basic.city",
@"nowCond": @"now.cond.txt",
@"nowTmp": @"now.tmp",
@"winddir": @"now.wind.dir",
@"windsc": @"now.wind.sc",
@"date": @"basic.update.loc",
@"maxTmp": @"daily_forecast.tmp.max",
@"minTmp": @"daily_forecast.tmp.min",
@"weatherqlty": @"aqi.city.qlty"
};
}4、当然要接受到JSON数据要调用下面的方法,并且传入带有你要的数据的字典
//创建NSDictionary
NSData *JSONData = ...//接口的响应数据
NSDictionary *JSONDict = [NSJSONSerialization JSONObjectWithData: JSONData options: error: nil]; //使用MTLJSONSerialization创建模型对象
CATProfile *profile = [MTLJSONAdapter modelOfClass: CATProfile.class fromJSONDictionary: JSONDict error: NULL];经过重复的练习,熟悉了用Mantle把JSON数据转模型之后,我就开始搭建App的UI了
- 第三步,建立天气预报页面
(展示天气页面)
这里主要懒加载了一个backgroundView作为背景图片,一个tableView以及多个XIB文件做成的Cell组成,我参考手机上自带的天气App做了一点美化,就是添加一个tableHeaderView,然后在上面添加一个ScrollView,在ScrollView上显示城市和日期,达到它一直悬浮在最上层的效果,下面的cell都在它底下滑过。(后来发现其实这里可以不添加tableHeaderView,把tableView的位置下移就好了。。。)=====================10.12日编辑==============================
对界面进行了调整,继续ing。。。 - 第四步,创建UIpagecontrol
基本定好天气预报信息如何展示之后,就要想,怎么展示多个天气页面呢?为了实现这个需求,我想到了用UIpagecontrol
这里主要用到一下属性和方法@property(nonatomic,strong) NSMutableArray *viewControllerArr; // 存放视图的数组
@property(nonatomic,assign) NSInteger curPage ; // 记录当前
@property(nonatomic,assign) NSInteger totalPages ; // 记录总页数 // ***翻页方法
// 往后翻
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
self.curPage = ((ViewController *)viewController).page;
UIImage *bgImg = [self createImageWithColor:((ViewController *)viewController).view.backgroundColor];
[self.navigationController.navigationBar setBackgroundImage:bgImg forBarMetrics:UIBarMetricsDefault];
self.pageControl.currentPage = self.curPage;
if (self.curPage < self.totalPages - && self.curPage != self.totalPages) {
return self.viewControllerArr[self.curPage + ];
}else{
return nil;
}
} // 往前翻
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{
self.curPage = ((ViewController *)viewController).page;
UIImage *bgImg = [self createImageWithColor:((ViewController *)viewController).view.backgroundColor];
[self.navigationController.navigationBar setBackgroundImage:bgImg forBarMetrics:UIBarMetricsDefault];
self.pageControl.currentPage = self.curPage;
if (self.curPage > && self.curPage != self.totalPages) {
return self.viewControllerArr[self.curPage - ];
}else{
return nil;
}
} - 第五步,添加城市,使用searchBar
实现这个需求,我选择在navigationBar 上添加一个按钮,跳转到一个带搜索栏的视图,实现输入城市名字,添加天气页面的功能
这里的难点是,添加视图后,UIpagecontrol的页面添加和翻页逻辑问题,经过一段时间努力还是解决了。 - 第六步,添加第三方侧栏LLSlideMenu
我想使用这个侧栏管理天气页面,因为我是用一个数组存储城市名字去加载天气页面的,所以我的思路是,在侧栏里面添加一个tableview,然后把数组的每一个元素显示上去,然后实验tableviewcell的编辑方法,达到移除相应的cell,即删除相应的城市名字和城市页面。
=====================10.20日编辑==============================
更新了程序运行的某些逻辑性问题,及以下 - 第七步,添加页面下拉刷新功能
这里使用的是李明杰老师的MJRefresh,简单易用,好好看文档就能上手,想当初也是看李明杰老师的iOS视频入门的,真心膜拜。 - 第八步,添加网络状态判断,用hud提示完善用户体验
这里使用的是iOS自带的框架SystemConfiguration.framework,并往项目里加入Reachability.h和.m文件
编写自己的类,并添加类方法去判断网络状态+ (NSInteger)networkStatus
{
Reachability *reachability = [Reachability reachabilityWithHostName:@"http://www.heweather.com"];//网址可改
return [reachability currentReachabilityStatus];
} - 第九步,实现程序从后天进入活跃状态,自动更新数据
涉及到程序生命周期的知识,参考之前自己的文章http://www.cnblogs.com/jierism/p/5730373.html,使用“通知”,让程序从后台进入活跃状态时调用更新数据的方法,思路是获取上次请求数据时的时间与当前系统时间比较,大于60分钟则更新数据 - 第十步,用Coredata存储数据
1.添加框架
2.建立实体
3.搭建上下文环境
使用这段万能的代码,只需把@“DataModel”修改为你相应数据模型的文件名 // 以下代码用于加载之前所定义的数据模型,并连接到一个SQLite数据存储中。
// 实际上任何采用Core Data的应用,以下代码的内容都是相同的。
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel == nil) {
NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"DataModel" ofType:@"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return _managedObjectModel;
} - (NSString *)documentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths lastObject];
return documentsDirectory;
} - (NSString *)dataStorePath
{
return [[self documentsDirectory] stringByAppendingPathComponent:@"DataStore.sqlite"];
} - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator == nil) {
NSURL *storeURL = [NSURL fileURLWithPath:[self dataStorePath]];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:self.managedObjectModel];
NSError *error; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Error adding persistent store %@,%@",error,[error userInfo]); abort();
}
}
return _persistentStoreCoordinator;
} -(NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext == nil) {
NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator; if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
}
return _managedObjectContext;
}4.编写保存数据和查询数据的方法,并在程序需要的地方调用
可以参考http://blog.csdn.net/q199109106q/article/details/8563438这篇博客入门- 到此程序的主要功能算是搞定了,后面还在考虑添加其他功能。。。在侧栏里面实现,大家有什么好点子可以推荐一下。
=====================11.2日编辑==============================
- 第十一步,实现给图片添加天气信息水印的功能
这个idea是在我学习Quartz 2D相关知识的时候萌生出来的,因为之前也用过QQ上的水印相机,感觉还挺有意思的,所以我就给我的App增加了这个功能,当然,技术有限,这个功能只能在生成后才能看见效果,并不能做到预览效果,其实我也想实现像一些水印相机App那样,在拍摄过程中就能看到水印。。。只能说技术有待提高。
实现:1.使用到UIImagePickerController和UIActionSheet,实现访问相机和相册功能
2.核心方法如下// 在图片上加水印
+ (instancetype)imageWithImage:(UIImage *)image andViewController:(ViewController *)controller
{ // 开启位图上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, );
[image drawAtPoint:CGPointZero]; // 设置文字的样式 NSDictionary *CityDict = @{
NSFontAttributeName : [UIFont fontWithName:@"KaiTi_GB2312" size: ],
NSForegroundColorAttributeName : [UIColor whiteColor]
};
NSDictionary *dict = @{
NSFontAttributeName : [UIFont fontWithName:@"KaiTi_GB2312" size: ],
NSForegroundColorAttributeName : [UIColor whiteColor]
}; CGFloat cityX = image.size.width - image.size.width / ;
CGFloat cityY = image.size.height / ;
// 画上城市名
[controller.cityName drawAtPoint:CGPointMake(cityX , cityY) withAttributes:CityDict]; CGFloat imgX = cityX + ;
CGFloat imgY = cityY - ;
CGFloat imgW = ;
// 画上天气图片
UIImage *condImg = [UIImage stringWithWeather:controller.jsonDic[@"now"][@"cond"][@"txt"]];
[condImg drawInRect:CGRectMake(imgX, imgY, imgW , imgW)]; CGFloat tempX = cityX + ;
CGFloat tempY = cityY + ; // 画上温度计
UIImage *shape = [UIImage imageNamed:@"Shape"];
[shape drawInRect:CGRectMake(tempX-, tempY, , )];
// 画上温度和天气情况
NSString *tempAndCond = [NSString stringWithFormat:@"%@℃ %@",controller.jsonDic[@"now"][@"tmp"],controller.jsonDic[@"now"][@"cond"][@"txt"]];
[tempAndCond drawAtPoint:CGPointMake(tempX, tempY) withAttributes:dict];
// 画上APP标记
NSString *ts = @"天\n时";
[ts drawInRect:CGRectMake(, image.size.height - ,,) withAttributes:dict]; // 获得新图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); //关闭上下文
UIGraphicsEndImageContext(); return newImage; }使用:翻到你想要显示的城市天气页面,选择照片或者拍摄,完了之后再相册就能查看到生成的图片
效果图: - 另外修改了一下界面
=====================11.8日编辑==============================
最近和风天气的API更新了,所以我的一些URL进行了修改。现在API的付费版本可以查询外国的天气了~ - 第十二步,新增了一个UISwitch按钮,实现用户可以选择是否自动更新天气信息,并用偏好设置记录它的开关状态,只需几步
// 保存
- (void)isRefrash:(UISwitch *)sender
{
// [NSUserDefaults standardUserDefaults]可以直接操作偏好设置文件夹
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // 自动帮我们生成一个plist文件存放在偏好设置的文件夹
[defaults setBool:sender.on forKey:@"switchStatus"]; // 同步:把内存中的数据和沙盒同步
[defaults synchronize];
} // 在UISwitch加载时读取状态
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[self.refashSwitch setOn:[defaults boolForKey:@"switchStatus"]]; - 第十三步,学习了一下sketch的简单操作,给自己的App做了个图标(ps:修改了好多次。。。)
毕业设计--天气预报App的更多相关文章
- android入门学习-天气预报app(一)
引言 学习<android第一行代码>根据书本开发的天气预报app,主要用于熟练操作android开发(android studio3.0平台). 今天主要分享一下从服务器上获取天气信息, ...
- 用Swift实现一款天气预报APP(三)
这个系列的目录: 用Swift实现一款天气预报APP(一) 用Swift实现一款天气预报APP(二) 用Swift实现一款天气预报APP(三) 通过前面的学习,一个天气预报的APP已经基本可用了.至少 ...
- 用Swift实现一款天气预报APP(二)
这个系列的目录: 用Swift实现一款天气预报APP(一) 用Swift实现一款天气预报APP(二) 用Swift实现一款天气预报APP(三) 上篇中主要讲了界面的一些内容,这篇主要讨论网络请求,获得 ...
- 用Swift实现一款天气预报APP(一)
这个系列的目录: 用Swift实现一款天气预报APP(一) 用Swift实现一款天气预报APP(二) 用Swift实现一款天气预报APP(三) Swift作为现在苹果极力推广的语言,发展的非常快.这个 ...
- 基于Android开发的天气预报app(源码下载)
原文:基于Android开发的天气预报app(源码下载) 基于AndroidStudio环境开发的天气app -系统总体介绍:本天气app使用AndroidStudio这个IDE工具在Windows1 ...
- 天气预报APP(1)
一个天气预报APP至少应该具备以下功能: *可以罗列出全国所有的省.市.县: *可以查看全国任意城市的天气信息: *可以自由的切换城市,去查看其他城市的天气: *提供手动更新以及后台自动更新天气的功能 ...
- 69.Android之天气预报app
最近买了本书<Android第一行代码>,通篇看了下感觉不错,书本最后有个实战项目酷欧天气,闲来无事就照着敲了一遍代码,主要在请求天气接口和背景优化做了些小改动,现在来记录下. (1) a ...
- 2.15 学习总结 之 天气预报APP volley(HTTP库)之StringRequest
一.说在前面 昨天 学习了序列化的相关知识 今天 1.学习 volley(HTTP库)的 StringRequest请求 2.使用序列化完成相关案例 遇到问题 请求到的参数的出现中文乱码问题 ...
- 天气预报APP(2)
之前实现了能够罗列可以罗列出全国所有的省.市.县,然后就是查询全国任意城市的天气信息.查询天气信息使用的是和风天气的api,这个api获得的天气信息是JSON格式的. 使用GSON库解析JSON数据的 ...
随机推荐
- linux内核值shmmax问题
问题:(rac安装过程中grid检测) Please run the following script on each node as "root" user to execut ...
- ylbtech-QQ(腾讯)-群空间-数据库设计
ylbtech-DatabaseDesgin:ylbtech-QQ(腾讯)-群空间-数据库设计 DatabaseName:QQ-群空间 Model:群相册.群共享.群论坛.群成员.留言板.公告.6个模 ...
- 让 PowerDesigner 支持 SQLite!
让 PowerDesigner 支持 SQLite! PowerDesigner是一个功能强大的数据库设计软件,最近正在用其设计新系统的数据库,但由于在项目初级阶段,希望使用轻量级的 SQLite ...
- 笔记《Java程序性能优化 让你的Java程序更快、更稳定》 第二章 设计调优
2.1 善用设计模式 23 (1) 1. 设计模式好处: 2.1.1 单例模式 23 (6) 1. 单例模式是一种对象创建模式,用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例: 2. ...
- cocos2dx 内存管理的理解
关于引擎内存管理的细节,网上有大量的详解,这里概括一下: cocos2d-x 的世界是基于 CCObject 类构建的,所以内存管理的本质就是管理一个个 CCObject. //CCObject 内部 ...
- Struts2注解 特别注意
1 Struts2注解的作用 使用注解可以用来替换struts.xml配置文件!!! 2 导包 必须导入struts2-convention-plugin-2.3.15.jar包,它在struts2安 ...
- 黑马程序员——OC的内存管理学习小结
内存管理在Objective-C中的重要性就像指针在C语言中的重要程序一样. 虽然作为一门高级语言,但OC却没有内存回收机制.这就需要开发者来对动态内存进行管理.OC中内存管理的范围是:任何继承了NS ...
- Mac下用命令行直接批量转换文本编码到UTF8
由于近期在Mac下写Android程序,下载的一些Demo由于编码问题源码里的汉字出现乱码,文件比较多,所以想批量解决下文件的编码问题. Mac下有以下两种方式可以解决: A. 文件名的编码:Mac的 ...
- stardict dict
stardict在sourceforge项目里的词典都不见,估计是由于版权方面的问题导致的,不过以前那些还是可以继续用的,没有下载的可以备份一份.每个字典文件夹里都有一个.ifo文件,可以用记事本打开 ...
- Use weakref module in a cache or mapping
The weakref module allows the Python programmer to create weak references to objects. In the followi ...