畢業設計--天氣預報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:修改了好屢次。。。)
相關文章
相關標籤/搜索