轉自:sjpsega's Blog
開始
打開Xcode並執行File/New/Project。選擇Application/Empty Application。將項目命名為SimpleWeather,單擊下一步,選擇一個目錄去保存你的項目,然後點擊Create。 現在,你的基礎項目已經完成。下一步是集成你的第三方工具。但首先你要關閉Xcode,確保他不會影響下一步。
Cocoapods
你將要下載Cocoapods的代碼,在Xcode項目中添加文件來使用,並配置項目需要的設置。
Mantle
Mantle是由於Github團隊開發的,目的是去除Objective-C把JSON數據轉為NSObject子類的所有樣板代碼。Mantle也能做數據轉換,通過一種神奇的方式把JSON原始數據(strings, ints, floats)轉換為復雜數據,比如NSDate, NSURL, 甚至是自定義類。
LBBlurredImage
LBBlurredImage是一個繼承自UIImageView,輕而易舉使圖像模糊的項目。你將僅僅用一行代碼來創建一個神奇的模糊效果。
TSMessages
TSMessages 是另一個非常簡單的庫,用來顯示浮層警告和通知。當出現錯誤信息而不直接影響用戶的時候,最好使用浮層來代替模態窗口(例如UIAlertView),這樣你將盡可能減少對用戶的影響。
你將只用TSMessages,在網絡失去連接或API錯誤的時候。如果發生錯誤,你將看到類似這樣的一個浮層:
ReactiveCocoa
最後,你將使用到ReactiveCocoa,他也來自於GitHub團隊。ReactiveCocoa給Objective-C帶來了函數編程,類似與.NET的Reactive Extensions。你將在第二部分花費大部分時間去實現ReactiveCocoa。
設置你的Cocoapods
設置你的Cocoapods,先要確保你已經安裝了Cocoapods。為此,打開命令行程序,並輸入。
確保你已經選擇SimpleWeather項目,如圖所示: Select SimpleWeather Project
構建並運行您的App,以確保一切工作正常:
打開WXController.m然後用如下所示替換-viewDidLoad方法:
在紅色背景下,狀態欄有點不夠清晰。幸運的是,有一個簡單的方法,使狀態欄更清晰易讀。
在iOS7,UIViewController有一個新的API,用來控制狀態欄的外觀。打開WXController,直接添加下面的代碼到-viewDidLoad:方法下:
設置你的App視圖
現在是時候讓你的App接近生活。下載這個項目的圖片,並解壓縮到一個合適的位置。這個壓縮包的背景圖片出自Flickr用戶idleformat之手,天氣圖片出自Dribbble用戶heeyeun之手。
切換回Xcode,單擊File/Add Files to “SimpleWeather”….定位到你剛剛解壓縮的圖片文件夾並選擇它。選擇Copy items into destination group’s folder (if needed),然後單擊Add。
打開WXController.h, 添加如下委托協議:
0
現在打開WXController.m。 小提示:你可以使用Control-Command-Up的快捷鍵來實現.h和.m文件之間的快速切換。 添加如下代碼到WXController.m頂部:1
LBBlurredImage.h包含在Cocoapods引入的LBBlurredImage項目,你會使用這個庫來模糊背景圖片。 應該有一個空的私有接口樣板在WXController imports的下方。它具有以下屬性:2
現在,是時候在項目中創建並設置視圖。 下面是你App的分解圖,記住,table view將是透明的:
為了實現動態模糊效果,在你的App中,你會根據App的滾動來改變模糊圖像的alpha值。
打開WXController.m,使用如下代碼來,替換掉-viewDidLoad中設置背景色的代碼:
3
這是非常簡單的代碼: 1.獲取並存儲屏幕高度。之後,你將在用分頁的方式來顯示所有天氣??數據時,使用它。 2.創建一個靜態的背景圖,並添加到視圖上。 3.使用LBBlurredImage來創建一個模糊的背景圖像,並設置alpha為0,使得開始backgroundImageView是可見的。 4.創建tableview來處理所有的數據呈現。 設置WXController為delegate和dataSource,以及滾動視圖的delegate。請注意,設置pagingEnabled為YES。 添加如下UITableView的delegate和dataSource的代碼到WXController.m的@implementation塊中:4
Pragma mark是組織代碼的很好的一種方式。 你的table view有兩個部分,一個是每小時的天氣預報,另一個用於每日播報。table view的section數目,設置為2。 天氣預報的cell是不可選擇的。給他們一個半透明的黑色背景和白色文字。5
最後,添加如下代碼到WXController.m:6
在WXController.m中,你的視圖控制器調用該方法來編排其子視圖。 構建並運行你的App,看看你的視圖如何堆疊。
仔細看,你會看到所有空的table cell的cell分隔線。
仍然在-viewDidLoad中,添加下面的代碼來設置你的布局框架和邊距:
7
這是相當常規設置代碼,但這裡是怎麼回事: 1.設置table的header大小與屏幕相同。你將利用的UITableView的分頁來分隔頁面頁頭和每日每時的天氣預報部分。 2.創建inset(或padding)變量,以便您的所有標簽均勻分布並居中。 3.創建並初始化為各種視圖創建的高度變量。設置這些值作為常量,使得可以很容易地在需要的時候,配置和更改您的視圖設置。 4.使用常量和inset變量,為label和view創建框架。 5.復制圖標框,調整它,使文本具有一定的擴展空間,並將其移動到該圖標的右側。當我們把標簽添加到視圖,你會看到布局的效果。 添加如下代碼到-viewDidLoad:8
這是相當長的一塊代碼,但它真的只是在做設置各種控件的繁重工作。簡單的說: 1.設置當前view為你的table header。 2.構建每一個顯示氣象數據的標簽。 3.添加一個天氣圖標的圖像視圖。 構建並運行你的App,你應該可以看到你之前布局的所有所有view。下面的屏幕截圖顯示了使用手工布局的、所有標簽框在視覺上的顯示。
用手指輕輕推動table,當你滾動它的時候,應該會反彈。
獲取氣象數據
你會注意到,App顯示“Loading…”,但它不是真正地在工作。是時候獲取一些真正的天氣數據。
你會從OpenWeatherMap的API拉取數據。 OpenWeatherMap是一個非常棒的服務,旨在提供實時,准確,免費的天氣數據給任何人。雖然有很多天氣API,但他們大多要麼使用較舊的數據格式,如XML,或是有償服務 – 並且有時還相當昂貴。
你會遵循以下基本步驟,來獲你設備的位置的氣象數據:
1.找到設備的位置
2.從API端下載JSON數據
3.映射JSON到WXConditions和WXDailyForecasts
4.告訴UI有新數據了
開始創建你的天氣模型和數據管理類。單擊File/New/File…並選擇Cocoa Touch/Objective-C class。命名為WXClient並使其為NSObject的子類。
這樣再做三次創建以下類:
1.WXManager作為NSObject的子類
2.WXCondition作為MTLModel的子類
3.WXDailyForecast作為WXCondition的子類
全部完成?現在,你可以開始下一節,其中涉及映射和轉換您的天氣數據。
創建你的天氣模型
你的模型將使用Mantle,這使得數據映射和轉型非常簡單。
打開WXCondition.h如下列代碼,修改接口:
9
MTLJSONSerializing協議告訴Mantle序列化該對象如何從JSON映射到Objective-C的屬性。 這些都是你的天氣數據的屬性。你將會使用這些屬性的get set方法,但是當你要擴展App,這是一種很好的方法來訪問數據。 這是一個簡單的輔助方法,從天氣狀況映射到圖像文件。 構建並運行App。失敗了…… 原因是你沒有從你的Cocoapods項目中引入Mantle。解決方法是,在WXCondition.h中,你需要把MTLModel.h替換為#import 。 現在構建並運行App。成功了。你會看到一些新的警告,但你可以忽略他們。 首先,你需要處理未實現的-imageName方法。 打開WXCondition.m,添加如下方法:0
創建一個靜態的NSDictionary,因為WXCondition的每個實例都將使用相同的數據映射。 天氣狀況與圖像文件的關系(例如“01d”代表“weather-clear.png”)。 聲明獲取圖像文件名的公有方法。 看一看從OpenWeatherMap返回的JSON響應數據:1
你需要把嵌套的JSON值映射到Objective-C的屬性。嵌套的JSON值是元素,如溫度,即上面看到的main節點。 要做到這一點,你將利用的Objective-C的Key-Value Coding和Mantle的MTLJSONAdapter。 還在WXCondition.m,通過添加+JSONKeyPathsByPropertyKey方法,“JSON到模型屬性”的映射,且該方法是MTLJSONSerializing協議的require。2
在這個方法裡,dictionary的key是WXCondition的屬性名稱,而dictionary的value是JSON的路徑。 您可能已經注意到,這裡有一個從JSON數據映射到Objective-C屬性的問題。屬性date是NSDate類型的,但JSON有一個Unix時間類型(sjpsega注:即從1970年1月1日0時0分0秒起至現在的總秒數)的NSInteger值。你需要完成兩者之間的轉換。 Mantle正好有一個功能來為你解決這個問題:MTLValueTransformer。這個類允許你聲明一個block,詳細說明值的相互轉換。 Mantle的轉換器語法有點怪。要創建一個為一個特定屬性的轉換器,,您可以添加一個以屬性名開頭和JSONTransformer結尾的類方法。 可能看實際代碼比試圖解釋它更容易理解,所以在WXCondition.m中添加以下為NSDate屬性設置的轉換器。3
使用blocks做屬性的轉換的工作,並返回一個MTLValueTransformer返回值。 您只需要詳細說明Unix時間和NSDate之間進行轉換一次,就可以重用-dateJSONTransformer方法為sunrise和sunset屬性做轉換。 下一個值轉型有點討厭,但它只是使用OpenWeatherMap的API,並自己的格式化JSON響應方式的結果。weather鍵對應的值是一個JSON數組,但你只關注單一的天氣狀況。 在WXCondition.m中,使用dateJSONTransformer相同的結構,您可以創建一個NSArray和NSString的之間的轉換。該解決方案提供如下:4
最後的轉換器只是為了格式化。 OpenWeatherAPI使用每秒/米的風速。由於您的App使用英制系統,你需要將其轉換為每小時/英裡。 在WXCondition.m的實現中添加以下轉換器的方法和宏定義。5
在OpenWeatherMap的API中有一個小的差異,你必須處理。看一看在位於當前狀況的響應和每日預測反應之間的溫度:6
current的第一個key是main,最高溫度存儲在key temp_max中,而daily forecast的第一個key是temp,最高溫度存儲在key max中。 key Temperature的差異放在一邊,其他都一樣。所以,你真正需要做的是修改daily forecasts的鍵映射。 打開WXDailyForecast.m重寫+JSONKeyPathsByPropertyKey方法:7
獲取WXCondition的映射,並創建它的可變副本。 你需要為daily forecast做的是改變max和min鍵映射。 返回新的映射。 構建並運行您的App,看起來和上次運行沒什麼改變,但好的一點是,App編譯和運行沒有任何錯誤。
何去何從?
你可以從這裡這裡完整程序。
在這部分教程中,您使用Cocoapods設置項目,增加視圖到控制器,編排視圖,並建立模型來反映你抓取的氣象數據。該App還沒有充分發揮作用,但是你成功用純代碼創建視圖,並學習了如何使用Mantle映射和轉換JSON數據。
接下來看看教程的第二部分,你將充實你的App,從weather API獲取數據,並在UI上顯示。您將使用新的iOS7 NSURLSession去下載數據,以及使用ReactiveCocoa把位置查找,天氣數據抓取和UI更新事件綁在一起。
iOS 7最佳實踐:一個天氣App案例