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的约束,最终效果见下图:


竖屏效果图

横屏效果图

建立 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)更容易阅读。

下图是我们需要的信息:

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

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

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

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

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

就是:

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

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

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

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

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

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

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

还是老样子,要确保 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:</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: "º")
                            
                            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()
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,175评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,674评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,151评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,597评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,505评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,969评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,455评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,118评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,227评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,213评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,214评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,928评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,512评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,616评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,848评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,228评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,772评论 2 339

推荐阅读更多精彩内容

  • 《裕语言》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 10...
    叶染柒丶阅读 25,597评论 5 18
  • 《ilua》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 1...
    叶染柒丶阅读 10,414评论 0 11
  • 像偏偏归来的燕子,再赞美您腊日的春光。 像茁壮成长的小树,再赞美:您雨露和太阳。 赞美您:黄河奔腾的海韵,赞美您桃...
    玲玲d阅读 255评论 0 0
  • 带着面具的人们在山腰上唱着低沉的赞歌,从厚重的乌云中传来阴暗的嘲笑。 人人都有形形色色的面具,有一张,叫善良;有一...
    梁宛央阅读 2,134评论 0 18