62課:創(chuàng)建一個天氣應(yīng)用

本課主要開發(fā)一個天氣App,運(yùn)用58和60課的知識點(diǎn):從網(wǎng)上下載數(shù)據(jù)和處理字符串。
課程筆記文集地址:Udemy課程:The Complete iOS 9 Developer Course - Build 18 Apps

1. 找到數(shù)據(jù)來源,也就是選好網(wǎng)址

網(wǎng)址為:http://www.weather-forecast.com/locations/Paris/forecasts/latest

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

2.布局storyboard

放置控件,設(shè)置好各種Auto Layout的約束,最終效果見下圖:


豎屏效果圖

橫屏效果圖

建立 Outlet 和 Action 連接:

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

3.獲取網(wǎng)絡(luò)數(shù)據(jù)
首先是Lecture 58中學(xué)到的代碼,幾乎沒有什么太大的變化,如下:

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完成之后再執(zhí)行,如果沒有完成,則不執(zhí)行,如果無法執(zhí)行,也不執(zhí)行之后的代碼
  if let urlContent = data {
      let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)
      print (webContent)
  } else {
    // 這里可以寫出錯的提示神馬的
  }
}
task?.resume()

從打印出來代碼可以看出來,我們需要的數(shù)據(jù)只是其中一行,那么接下來需要做的事情就是把這一行從數(shù)據(jù)中提取出來。鼠標(biāo)右鍵查看源碼(谷歌瀏覽器),比起print(webContent)更容易閱讀。

下圖是我們需要的信息:

查看源碼之后找到對應(yīng)的部分:

所有的源碼實(shí)際上就是webContent,現(xiàn)在我們只需要這一小部分,那么怎么截取出來呢?

首先用上一節(jié)課學(xué)到的知識把webContent分成字符串類型的數(shù)組,這樣就方便取出需要的字段了。

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

那我們用哪個字符串來分割webContent呢?

就是:

3 Day Weather Forecast Summary:</b><span class="read-more-small"><span class="read-more-content"> <span class="phrase">

這段放到代碼中時要注意雙引號的問題,在Swift中,兩個雙引號之間表示是一個字符串,所以直接復(fù)制到代碼中后,還需要對代碼進(jìn)行小小的修改,在雙引號前面加上 \ 表示這是一個標(biāo)點(diǎn)符號不是表示字符串:

let websiteArray = webContent?.componentsSeparatedByString("3 Day Weather Forecast Summary:</b><span class=\"read-more-small\"><span class=\"read-more-content\"> <span class=\"phrase\">")

這里最好確保websiteArray這個數(shù)組里真正有內(nèi)容,如果網(wǎng)頁的布局變了,或者網(wǎng)站停止服務(wù)了,掛掉了之類的,數(shù)組里就不會有值,這樣空值出現(xiàn),會造成應(yīng)用崩潰,用if確保有值之后再去繼續(xù)往下走:

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

然后繼續(xù)websiteArray[1]中的內(nèi)容,最后得到我們想要的信息:

if websiteArray!.count > 1 {
  let weatherArray = websiteArray![1].componentsSeparatedByString("</span")
}

還是老樣子,要確保 weatherArray 這個數(shù)組里真的有內(nèi)容:

if weatherArray!.count > 1 {
    let weatherSummary = weatherArray[0]
    將weatherSummary賦值給對應(yīng)的Label控件
}

將weatherSummary賦值給對應(yīng)的Label控件,這個步驟可以用多線程的方法放到主線程來做:

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

運(yùn)行之后發(fā)現(xiàn),weatherSummary里的攝氏度沒有顯示出來,所以我們用上一節(jié)的知識替換出正確的符號:

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

攝氏度的快捷鍵:Option+Alt+Z

4.更換城市
我們現(xiàn)在使用的是巴黎的天氣情況,如果是其他城市的情況怎么辦呢?
根據(jù)網(wǎng)站上的信息,我們發(fā)現(xiàn),只需要替換網(wǎng)址中的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 {
//這里繼續(xù)往下的所有操作
}

5.錯誤提示
如果用戶輸入了錯誤的信息,需要提示一下,我們沒有獲取到城市信息,不然用戶看到程序界面沒有變化,以為死掉了呢。

聲明一個 wasSuccessful 的布爾值,當(dāng)為false時,更新Label的內(nèi)容。

6.完整代碼
到這里,代碼就已經(jīng)全部寫完了。

全部代碼如下:


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:</b><span class=\"read-more-small\"><span class=\"read-more-content\"> <span class=\"phrase\">")
                    
                    if websiteArray.count > 1 {
                        
                        let weatherArray = websiteArray[1].componentsSeparatedByString("</span>")
                        
                        if weatherArray.count > 1 {
                            
                            wasSuccessful = true
                            
                            let weatherSummary = weatherArray[0].stringByReplacingOccurrencesOfString("°", withString: "o")
                            
                            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()
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 《裕語言》速成開發(fā)手冊3.0 官方用戶交流:iApp開發(fā)交流(1) 239547050iApp開發(fā)交流(2) 10...
    葉染柒丶閱讀 27,890評論 5 19
  • 《ilua》速成開發(fā)手冊3.0 官方用戶交流:iApp開發(fā)交流(1) 239547050iApp開發(fā)交流(2) 1...
    葉染柒丶閱讀 11,019評論 0 11
  • 像偏偏歸來的燕子,再贊美您臘日的春光。 像茁壯成長的小樹,再贊美:您雨露和太陽。 贊美您:黃河奔騰的海韻,贊美您桃...
    玲玲d閱讀 274評論 0 0
  • 帶著面具的人們在山腰上唱著低沉的贊歌,從厚重的烏云中傳來陰暗的嘲笑。 人人都有形形色色的面具,有一張,叫善良;有一...
    梁宛央閱讀 2,157評論 0 18