62课:创建一个天气应用

本课主要开发一个天气App,运用58和60课的知识点:从网上下载数据和处理字符串。
课程笔记文集地址:Udemy课程:The Complete iOS 9 Developer Course - Build 18 Apps

1. 找到数据来源,也就是选好网址

网址为:http://www.weather-forecast.com/locations/Paris/forecasts/latest

所以需要去.plist文件里输入:
NSAppTransportSecurity Dictionary (1 item) 这一个item就是-> NSAllowsArbitraryLoads Boolean YES

2.布局storyboard

放置控件,设置好各种Auto Layout的约束,最终效果见下图:


62课:创建一个天气应用_第1张图片
竖屏效果图

62课:创建一个天气应用_第2张图片
横屏效果图

建立 Outlet 和 Action 连接:

@IBOutlet var cityTextField: UITextField!
@IBOutlet var resultLabel: UILabel!
@IBOutlet var findWeather(sender: AnyObject) {
    //这是Button的Action连接
}

3.获取网络数据
首先是Lecture 58中学到的代码,几乎没有什么太大的变化,如下:

let url = NSURL(string:"http://www.weather-forecast.com/locations/Paris/forecasts/latest")
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
  //这里的代码都是task完成之后再执行,如果没有完成,则不执行,如果无法执行,也不执行之后的代码
  if let urlContent = data {
      let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)
      print (webContent)
  } else {
    // 这里可以写出错的提示神马的
  }
}
task?.resume()

从打印出来代码可以看出来,我们需要的数据只是其中一行,那么接下来需要做的事情就是把这一行从数据中提取出来。鼠标右键查看源码(谷歌浏览器),比起print(webContent)更容易阅读。

下图是我们需要的信息:

62课:创建一个天气应用_第3张图片

查看源码之后找到对应的部分:

62课:创建一个天气应用_第4张图片

所有的源码实际上就是webContent,现在我们只需要这一小部分,那么怎么截取出来呢?

首先用上一节课学到的知识把webContent分成字符串类型的数组,这样就方便取出需要的字段了。

newTypeString.componentsSeparatedByString("某某字符串")

那我们用哪个字符串来分割webContent呢?

就是:

3 Day Weather Forecast Summary:

这段放到代码中时要注意双引号的问题,在Swift中,两个双引号之间表示是一个字符串,所以直接复制到代码中后,还需要对代码进行小小的修改,在双引号前面加上 \ 表示这是一个标点符号不是表示字符串:

let websiteArray = webContent?.componentsSeparatedByString("3 Day Weather Forecast Summary: ")
62课:创建一个天气应用_第5张图片

这里最好确保websiteArray这个数组里真正有内容,如果网页的布局变了,或者网站停止服务了,挂掉了之类的,数组里就不会有值,这样空值出现,会造成应用崩溃,用if确保有值之后再去继续往下走:

if websiteArray!.count > 1 {
    print(websiteArray![1])
}

然后继续websiteArray[1]中的内容,最后得到我们想要的信息:

if websiteArray!.count > 1 {
  let weatherArray = websiteArray![1].componentsSeparatedByString("

还是老样子,要确保 weatherArray 这个数组里真的有内容:

if weatherArray!.count > 1 {
    let weatherSummary = weatherArray[0]
    将weatherSummary赋值给对应的Label控件
}

将weatherSummary赋值给对应的Label控件,这个步骤可以用多线程的方法放到主线程来做:

if weatherArray!.count > 1 {
    let weatherSummary = weatherArray[0]
    
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.resultLabel.text = weatherSummary
})
}

运行之后发现,weatherSummary里的摄氏度没有显示出来,所以我们用上一节的知识替换出正确的符号:

let weatherSummary = weatherArray[0].stringByReplacingOccurrencesOfString("°", withString:"��¸")

摄氏度的快捷键:Option+Alt+Z

4.更换城市
我们现在使用的是巴黎的天气情况,如果是其他城市的情况怎么办呢?
根据网站上的信息,我们发现,只需要替换网址中的Paris即可。

let url = NSURL(string:"http://www.weather-forecast.com/locations/" +cityTextField.text! +"/forecasts/latest")!

不过输入带有空格的城市如 San Francisco,会造成程序崩溃,解决方法:

let url = NSURL(string:"http://www.weather-forecast.com/locations/" + cityTextField.stringByReplacingOccurrencesOfString(" ", withString:"��-") + "/forecasts/latest")!

输入乱七八糟的字符也会造成崩溃,解决方法:

let attemptedUrl = NSURL(string:"http://www.weather-forecast.com/locations/" + cityTextField.stringByReplacingOccurrencesOfString(" ", withString:"��-") + "/forecasts/latest")!

if let url = attemptedUrl {
//这里继续往下的所有操作
}

5.错误提示
如果用户输入了错误的信息,需要提示一下,我们没有获取到城市信息,不然用户看到程序界面没有变化,以为死掉了呢。

声明一个 wasSuccessful 的布尔值,当为false时,更新Label的内容。

6.完整代码
到这里,代码就已经全部写完了。

全部代码如下:


import UIKit

class ViewController: UIViewController {
    
    @IBOutlet var cityTextField: UITextField!
    
    @IBOutlet var resultLabel: UILabel!
    
    @IBAction func findWeather(sender: AnyObject) {
        
        var wasSuccessful = false
        
        let attemptedUrl = NSURL(string: "http://www.weather-forecast.com/locations/" + cityTextField.text!.stringByReplacingOccurrencesOfString(" ", withString: "-") + "/forecasts/latest")
        
        if let url = attemptedUrl {
            
            let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
                
                if let urlContent = data {
                    
                    let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)
                    
                    let websiteArray = webContent!.componentsSeparatedByString("3 Day Weather Forecast Summary: ")
                    
                    if websiteArray.count > 1 {
                        
                        let weatherArray = websiteArray[1].componentsSeparatedByString("")
                        
                        if weatherArray.count > 1 {
                            
                            wasSuccessful = true
                            
                            let weatherSummary = weatherArray[0].stringByReplacingOccurrencesOfString("°", withString: "º")
                            
                            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                                
                                self.resultLabel.text = weatherSummary
                                
                            })
                        }
                    }
                }
                
                if wasSuccessful == false {
                    
                    self.resultLabel.text = "Couldn't find the weather for that city - please try again."
                }
            }
            
            task.resume()
            
        } else {
            self.resultLabel.text = "Couldn't find the weather for that city - please try again."
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

你可能感兴趣的:(62课:创建一个天气应用)