毕业设计--天气预报App

  9月中旬,开始动手作个人毕业设计了,以前一直在纠结作啥,后来想一想,既然是作毕业设计,那就大胆地作点本身没接触过的东西吧。而后网上查找资料得知作天气预报须要用到开放的API,并且要用那种如今还在维护的,并且又免费的(对于咱们学生党来讲,这个是挺好的)。天气预报App的核心是从天气API请求数据,请求获得的通常是JSON数据(这个JSON数据以前都没接触过),而后把JSON数据解析,而后在视图上显示出来。总得来讲,这里应该涉及到“网络请求”,“JSON解析”这两个大块吧,正好用来学习新的东西,而且练练手,因而就决定作个天气预报的App了。html

  • 第一步,找天气API
    各类百度,而后找到了比较新的网站,分别是“心知天气”和“和风天气”。都须要注册,注册以后会获得一个key,用来进行数据请求的。两个网站都有付费和免费的两种选择,如图,比较完以后,二话不说,选择了和风天气的API。

 

  • 第二步,找解析JSON的第三方框架
    各类百度以后也找到了你们推荐的一些,如:JSONKit、Mantle、AFNetworking、SBJSON、MJExtension等等等等。。。最后参考一篇教程,仍是选择了Mantle,固然不是说其余很差用,我的喜爱而已。
    Mantle的使用也很简单。
    一、新建一个继承自MTLModel的类,并让他遵循<MTLJSONSerializing>协议,注意这里还要#import <MTLModel.h>
    二、在.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;    // 空气质量
    
    
    @end

    三、在.m文件中实现类方法,实现JSON数据到模型的映射sql

    + (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"
                 };
    }

    四、固然要接受到JSON数据要调用下面的方法,而且传入带有你要的数据的字典json

    //建立NSDictionary
    NSData *JSONData = ...//接口的响应数据
    NSDictionary *JSONDict = [NSJSONSerialization JSONObjectWithData: JSONData options: 0 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 - 1 && self.curPage != self.totalPages) {
            return self.viewControllerArr[self.curPage + 1];
        }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 > 0 && self.curPage != self.totalPages) {
            return self.viewControllerArr[self.curPage - 1];
        }else{
            return nil;
        }
    }
    View Code
  • 第五步,添加城市,使用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, 0);
        [image drawAtPoint:CGPointZero];
        
        // 设置文字的样式
    
        NSDictionary *CityDict = @{
                               NSFontAttributeName : [UIFont fontWithName:@"KaiTi_GB2312" size: 40],
                               NSForegroundColorAttributeName : [UIColor whiteColor]
                               };
        NSDictionary *dict = @{
                                   NSFontAttributeName : [UIFont fontWithName:@"KaiTi_GB2312" size: 25],
                                   NSForegroundColorAttributeName : [UIColor whiteColor]
                                   };
        
        CGFloat cityX = image.size.width - image.size.width / 4;
        CGFloat cityY = image.size.height / 13;
        // 画上城市名
        [controller.cityName drawAtPoint:CGPointMake(cityX , cityY) withAttributes:CityDict];
        
        CGFloat imgX = cityX + 80;
        CGFloat imgY = cityY - 20;
        CGFloat imgW = 80;
        // 画上天气图片
        UIImage *condImg = [UIImage stringWithWeather:controller.jsonDic[@"now"][@"cond"][@"txt"]];
        [condImg drawInRect:CGRectMake(imgX, imgY, imgW , imgW)];
        
        CGFloat tempX = cityX + 40;
        CGFloat tempY = cityY + 60;
        
        // 画上温度计
        UIImage *shape = [UIImage imageNamed:@"Shape"];
        [shape drawInRect:CGRectMake(tempX-20, tempY, 14, 22)];
        // 画上温度和天气状况
        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(10, image.size.height - 80,40,80) 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:修改了好屡次。。。)
相关文章
相关标签/搜索