From ed766134d8c102cce02b96b4b9d5acb31dda74e7 Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 10 Jun 2016 18:07:02 +0200 Subject: [PATCH 1/2] WeatherClient --- APIClient.xcodeproj/project.pbxproj | 58 +++- APIClient/AppDelegate.swift | 21 +- APIClient/Base.lproj/LaunchScreen.storyboard | 2 +- APIClient/Base.lproj/Main.storyboard | 257 +++++++++++++++++- APIClient/City.swift | 51 ++++ APIClient/Forecast.swift | 193 +++++++++++++ APIClient/ForecastAPI.swift | 69 +++++ APIClient/GoogleGeocodingAPI.swift | 68 +++++ APIClient/Images.xcassets/Contents.json | 6 + .../Sunrise-50.imageset/Contents.json | 21 ++ .../Sunrise-50.imageset/Sunrise-50.png | Bin 0 -> 653 bytes .../Sunset-50.imageset/Contents.json | 21 ++ .../Sunset-50.imageset/Sunset-50.png | Bin 0 -> 673 bytes .../clear-day.imageset/Contents.json | 21 ++ .../clear-day.imageset/weather-3.png | Bin 0 -> 2326 bytes .../cloud.imageset/Contents.json | 21 ++ .../Images.xcassets/cloud.imageset/sky-2.png | Bin 0 -> 2276 bytes .../fog.imageset/Contents.json | 21 ++ .../fog.imageset/weather-2.png | Bin 0 -> 1091 bytes .../hail.imageset/Contents.json | 21 ++ .../Images.xcassets/hail.imageset/sky-3.png | Bin 0 -> 2323 bytes .../partly-cloudy-day.imageset/Contents.json | 21 ++ .../partly-cloudy-day.imageset/sky-4.png | Bin 0 -> 2642 bytes .../Contents.json | 21 ++ .../partly-cloudy-night.imageset/cloud.png | Bin 0 -> 2655 bytes .../rain.imageset/Contents.json | 21 ++ .../Images.xcassets/rain.imageset/sky.png | Bin 0 -> 2669 bytes .../sleet.imageset/Contents.json | 21 ++ .../Images.xcassets/sleet.imageset/sky-5.png | Bin 0 -> 2544 bytes .../snow.imageset/Contents.json | 21 ++ .../snow.imageset/weather-1.png | Bin 0 -> 4062 bytes .../thunderstorm.imageset/Contents.json | 21 ++ .../thunderstorm.imageset/weather.png | Bin 0 -> 2668 bytes .../wind.imageset/Contents.json | 21 ++ .../Images.xcassets/wind.imageset/sky-1.png | Bin 0 -> 2683 bytes APIClient/Info.plist | 4 +- APIClient/Weather.swift | 29 ++ APIClient/WeatherListViewController.swift | 41 +++ APIClient/WeatherTableViewCell.swift | 29 ++ APIClient/WeatherViewController.swift | 241 ++++++++++++++++ Podfile | 2 +- 41 files changed, 1325 insertions(+), 19 deletions(-) create mode 100644 APIClient/City.swift create mode 100644 APIClient/Forecast.swift create mode 100644 APIClient/ForecastAPI.swift create mode 100644 APIClient/GoogleGeocodingAPI.swift create mode 100644 APIClient/Images.xcassets/Contents.json create mode 100644 APIClient/Images.xcassets/Sunrise-50.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/Sunrise-50.imageset/Sunrise-50.png create mode 100644 APIClient/Images.xcassets/Sunset-50.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/Sunset-50.imageset/Sunset-50.png create mode 100644 APIClient/Images.xcassets/clear-day.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/clear-day.imageset/weather-3.png create mode 100644 APIClient/Images.xcassets/cloud.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/cloud.imageset/sky-2.png create mode 100644 APIClient/Images.xcassets/fog.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/fog.imageset/weather-2.png create mode 100644 APIClient/Images.xcassets/hail.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/hail.imageset/sky-3.png create mode 100644 APIClient/Images.xcassets/partly-cloudy-day.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/partly-cloudy-day.imageset/sky-4.png create mode 100644 APIClient/Images.xcassets/partly-cloudy-night.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/partly-cloudy-night.imageset/cloud.png create mode 100644 APIClient/Images.xcassets/rain.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/rain.imageset/sky.png create mode 100644 APIClient/Images.xcassets/sleet.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/sleet.imageset/sky-5.png create mode 100644 APIClient/Images.xcassets/snow.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/snow.imageset/weather-1.png create mode 100644 APIClient/Images.xcassets/thunderstorm.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/thunderstorm.imageset/weather.png create mode 100644 APIClient/Images.xcassets/wind.imageset/Contents.json create mode 100644 APIClient/Images.xcassets/wind.imageset/sky-1.png create mode 100644 APIClient/Weather.swift create mode 100644 APIClient/WeatherListViewController.swift create mode 100644 APIClient/WeatherTableViewCell.swift create mode 100644 APIClient/WeatherViewController.swift diff --git a/APIClient.xcodeproj/project.pbxproj b/APIClient.xcodeproj/project.pbxproj index d57524a..3345914 100644 --- a/APIClient.xcodeproj/project.pbxproj +++ b/APIClient.xcodeproj/project.pbxproj @@ -7,6 +7,15 @@ objects = { /* Begin PBXBuildFile section */ + 321A60FE1D09FD200024A145 /* Weather.swift in Sources */ = {isa = PBXBuildFile; fileRef = 321A60FD1D09FD200024A145 /* Weather.swift */; }; + 32284E5A1D04395C003BC1EF /* WeatherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32284E591D04395C003BC1EF /* WeatherViewController.swift */; }; + 32284E5C1D0442AF003BC1EF /* GoogleGeocodingAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32284E5B1D0442AF003BC1EF /* GoogleGeocodingAPI.swift */; }; + 32284E601D044FF7003BC1EF /* Forecast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32284E5F1D044FF7003BC1EF /* Forecast.swift */; }; + 324F0F8E1D0AD1FA00F24085 /* WeatherTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 324F0F8D1D0AD1FA00F24085 /* WeatherTableViewCell.swift */; }; + 32A28C161D057D9C002D41CA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 32A28C151D057D9C002D41CA /* Images.xcassets */; }; + 32A28C181D058880002D41CA /* ForecastAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32A28C171D058880002D41CA /* ForecastAPI.swift */; }; + 32A28C1A1D058A69002D41CA /* City.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32A28C191D058A69002D41CA /* City.swift */; }; + 32FBADA41D06306600D23B0D /* WeatherListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FBADA31D06306600D23B0D /* WeatherListViewController.swift */; }; 872A275C1CF0D87100A988C4 /* APIResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 872A275B1CF0D87100A988C4 /* APIResource.swift */; }; 874D06591CEF295E009A494D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874D06581CEF295E009A494D /* AppDelegate.swift */; }; 874D065E1CEF295E009A494D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 874D065C1CEF295E009A494D /* Main.storyboard */; }; @@ -16,8 +25,17 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 321A60FD1D09FD200024A145 /* Weather.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Weather.swift; sourceTree = ""; }; + 32284E591D04395C003BC1EF /* WeatherViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeatherViewController.swift; sourceTree = ""; }; + 32284E5B1D0442AF003BC1EF /* GoogleGeocodingAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GoogleGeocodingAPI.swift; sourceTree = ""; }; + 32284E5F1D044FF7003BC1EF /* Forecast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Forecast.swift; sourceTree = ""; }; + 324F0F8D1D0AD1FA00F24085 /* WeatherTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeatherTableViewCell.swift; sourceTree = ""; }; + 32A28C151D057D9C002D41CA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 32A28C171D058880002D41CA /* ForecastAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ForecastAPI.swift; sourceTree = ""; }; + 32A28C191D058A69002D41CA /* City.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = City.swift; sourceTree = ""; }; + 32FBADA31D06306600D23B0D /* WeatherListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeatherListViewController.swift; sourceTree = ""; }; 872A275B1CF0D87100A988C4 /* APIResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIResource.swift; sourceTree = ""; }; - 874D06551CEF295E009A494D /* APIClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = APIClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 874D06551CEF295E009A494D /* WeatherClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WeatherClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; 874D06581CEF295E009A494D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 874D065D1CEF295E009A494D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 874D065F1CEF295E009A494D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -43,6 +61,9 @@ 872A27571CF0D4E200A988C4 /* View Controller */ = { isa = PBXGroup; children = ( + 32284E591D04395C003BC1EF /* WeatherViewController.swift */, + 32FBADA31D06306600D23B0D /* WeatherListViewController.swift */, + 324F0F8D1D0AD1FA00F24085 /* WeatherTableViewCell.swift */, ); name = "View Controller"; sourceTree = ""; @@ -58,6 +79,11 @@ isa = PBXGroup; children = ( 872A275B1CF0D87100A988C4 /* APIResource.swift */, + 32284E5B1D0442AF003BC1EF /* GoogleGeocodingAPI.swift */, + 32A28C171D058880002D41CA /* ForecastAPI.swift */, + 32284E5F1D044FF7003BC1EF /* Forecast.swift */, + 32A28C191D058A69002D41CA /* City.swift */, + 321A60FD1D09FD200024A145 /* Weather.swift */, ); name = Model; sourceTree = ""; @@ -85,7 +111,7 @@ 874D06561CEF295E009A494D /* Products */ = { isa = PBXGroup; children = ( - 874D06551CEF295E009A494D /* APIClient.app */, + 874D06551CEF295E009A494D /* WeatherClient.app */, ); name = Products; sourceTree = ""; @@ -99,6 +125,7 @@ 872A27581CF0D4EB00A988C4 /* View */, 872A27591CF0D64A00A988C4 /* Model */, 872A275A1CF0D65300A988C4 /* Supporting Files */, + 32A28C151D057D9C002D41CA /* Images.xcassets */, ); path = APIClient; sourceTree = ""; @@ -140,7 +167,7 @@ ); name = APIClient; productName = APIClient; - productReference = 874D06551CEF295E009A494D /* APIClient.app */; + productReference = 874D06551CEF295E009A494D /* WeatherClient.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -155,6 +182,7 @@ TargetAttributes = { 874D06541CEF295E009A494D = { CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = LS389VJ9WF; }; }; }; @@ -182,6 +210,7 @@ buildActionMask = 2147483647; files = ( 874D06631CEF295E009A494D /* LaunchScreen.storyboard in Resources */, + 32A28C161D057D9C002D41CA /* Images.xcassets in Resources */, 874D06601CEF295E009A494D /* Assets.xcassets in Resources */, 874D065E1CEF295E009A494D /* Main.storyboard in Resources */, ); @@ -242,8 +271,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 324F0F8E1D0AD1FA00F24085 /* WeatherTableViewCell.swift in Sources */, 872A275C1CF0D87100A988C4 /* APIResource.swift in Sources */, + 32A28C181D058880002D41CA /* ForecastAPI.swift in Sources */, + 32284E5C1D0442AF003BC1EF /* GoogleGeocodingAPI.swift in Sources */, + 32284E5A1D04395C003BC1EF /* WeatherViewController.swift in Sources */, + 321A60FE1D09FD200024A145 /* Weather.swift in Sources */, + 32284E601D044FF7003BC1EF /* Forecast.swift in Sources */, + 32FBADA41D06306600D23B0D /* WeatherListViewController.swift in Sources */, 874D06591CEF295E009A494D /* AppDelegate.swift in Sources */, + 32A28C1A1D058A69002D41CA /* City.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -359,10 +396,14 @@ baseConfigurationReference = 93EFAB13AE62F1B6FB2683B2 /* Pods-APIClient.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = APIClient/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "de.uni-heidelberg.ios-dev-kurs.APIClient"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = "de.uni-heidelberg.ios-dev-kurs.coli-n.APIClient"; + PRODUCT_NAME = WeatherClient; + PROVISIONING_PROFILE = ""; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -371,10 +412,15 @@ baseConfigurationReference = FFE13D543A95D28F27CFBDA4 /* Pods-APIClient.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = APIClient/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "de.uni-heidelberg.ios-dev-kurs.APIClient"; + "PRIVATE_HEADERS_FOLDER_PATH[sdk=*]" = "$(CONTENTS_FOLDER_PATH)/PrivateHeaders"; + PRODUCT_BUNDLE_IDENTIFIER = "de.uni-heidelberg.ios-dev-kurs.coli-n.APIClient"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; diff --git a/APIClient/AppDelegate.swift b/APIClient/AppDelegate.swift index 630c3ed..b415afa 100644 --- a/APIClient/AppDelegate.swift +++ b/APIClient/AppDelegate.swift @@ -7,14 +7,33 @@ // import UIKit +import Moya @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? + let googleAPI = MoyaProvider() + let forecastAPI = MoyaProvider() - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(avarication: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + + if let weatherviewcontroller = (window?.rootViewController as? UINavigationController)?.topViewController as? WeatherViewController { + + // Pass the PokeAPI Provider on to the root view controller + weatherviewcontroller.forecastAPI = forecastAPI + weatherviewcontroller.googleAPI = googleAPI + } + + return true + } + + // MARK: State Preservation + func application(application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool { + return true + } + func application(application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool { return true } diff --git a/APIClient/Base.lproj/LaunchScreen.storyboard b/APIClient/Base.lproj/LaunchScreen.storyboard index ebf48f6..f6e2022 100644 --- a/APIClient/Base.lproj/LaunchScreen.storyboard +++ b/APIClient/Base.lproj/LaunchScreen.storyboard @@ -1,5 +1,5 @@ - + diff --git a/APIClient/Base.lproj/Main.storyboard b/APIClient/Base.lproj/Main.storyboard index 69b2fbf..81dcfec 100644 --- a/APIClient/Base.lproj/Main.storyboard +++ b/APIClient/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -8,11 +8,23 @@ - - + + + + + + + + + + + + + + @@ -21,24 +33,253 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/APIClient/City.swift b/APIClient/City.swift new file mode 100644 index 0000000..627cab6 --- /dev/null +++ b/APIClient/City.swift @@ -0,0 +1,51 @@ +// +// City.swift +// APIClient +// +// Created by Colin Otchere on 06.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation +import Moya +import Freddy + +struct CityRawData: JSONDecodable{ + + + let status: String + let result: [CityDetail] + + init(json: JSON) throws { + self.status = try json.string("status") + self.result = try json.arrayOf("results") + } + + struct CityDetail:JSONDecodable { + let formatedAdress: String + let geometry: Geometry + init(json: JSON) throws { + self.formatedAdress = try json.string("formatted_address") + self.geometry = try json.decode("geometry") + } + } +} + +struct Geometry: JSONDecodable{ + + let location: Coordination + init(json: JSON) throws { + self.location = try json.decode("location") + } +} + +struct Coordination: JSONDecodable{ + + let lat: Double + let lng: Double + + init(json: JSON) throws { + self.lat = try json.double("lat") + self.lng = try json.double("lng") + } +} \ No newline at end of file diff --git a/APIClient/Forecast.swift b/APIClient/Forecast.swift new file mode 100644 index 0000000..93bdf27 --- /dev/null +++ b/APIClient/Forecast.swift @@ -0,0 +1,193 @@ +// +// Weather.swift +// APIClient +// +// Created by Colin Otchere on 05.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation +import Freddy +import UIKit + +struct WeatherRawData:JSONDecodable{ + + let currentWeather: Weather + let dailyWeather: Data + let timezone: String + + init(json: JSON) throws { + self.timezone = try json.string("timezone") + self.currentWeather = try json.decode("currently") + self.dailyWeather = try json.decode("daily") + } +} + +struct Data: JSONDecodable{ + + let data: [WeatherData] + + init(json: JSON) throws { + self.data = try json.arrayOf("data") + } +} +struct Weather:JSONDecodable{ + + let time: Int + let summary: String + let icon: String + var temperatur: Double + var summaryGer: String + + init(json: JSON) throws { + + self.summary = try json.string("summary") + self.time = try json.int("time") + self.icon = try json.string("icon") + self.temperatur = try json.double("temperature") + self.summaryGer = "" + convertToCelsius() + self.summaryGer = translate(self.icon) + } + + mutating func convertToCelsius(){ + self.temperatur = (self.temperatur - 32)*5/9 + } + + mutating func translate(weathertext: String) -> String{ + switch weathertext { + case "clear-day": + return "Heiter" + case "clear-night": + return "klare Nacht" + case "rain": + return "Regen" + case "snow": + return "Schnee" + case "sleet": + return "Schneeregen" + case "wind": + return "windig" + case "fog": + return "neblig" + case "cloudy": + return "bewölckt" + case "partly-cloudy-day": + return "" + case "partly-cloudy-night": + return "leicht bewölkt" + case "hail": + return "Hagel" + case "thunderstorm": + return "Gewitter" + case "tornado": + return "Tornado" + default: + return "keine Wetterdaten" + + } + } +} + +struct WeatherData: JSONDecodable{ + + var time: Double + var date:String + let icon: String + var sunriseTime: Double + var sunsetTime: Double + var minTemp: Double + var maxTemp: Double + var summaryGer: String + + var sunrise: String + var sunset: String + + init(json: JSON) throws { + self.time = try json.double("time") + self.icon = try json.string("icon") + self.sunriseTime = try json.double("sunriseTime") + self.sunsetTime = try json.double("sunsetTime") + self.minTemp = try json.double("temperatureMin") + self.maxTemp = try json.double("temperatureMax") + self.summaryGer = "av" + self.date = "" + self.sunrise="" + self.sunset="" + + self.minTemp = convertToCelsius(self.minTemp) + self.maxTemp = convertToCelsius(self.maxTemp) + + self.sunrise = convertUnixTimeToDate(self.sunriseTime) + self.sunset = convertUnixTimeToDate(self.sunsetTime) + + self.date = dayStringFromTime(self.time) + self.summaryGer = translateToGer(self.icon) + } + + mutating func convertToCelsius(temperatur: Double) -> Double{ + let tmpT = (temperatur - 32)*5/9 + return tmpT + } + + mutating func convertUnixTimeToDate(time: Double) -> String{ + + let dateFormatter = NSDateFormatter() + + dateFormatter.dateFormat = "hh:mm" + dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle + dateFormatter.timeZone = NSTimeZone.localTimeZone() + + let date = NSDate(timeIntervalSince1970: time) + + return dateFormatter.stringFromDate(date) + } + + mutating func dayStringFromTime(unixTime: Double) -> String { + + let dateFormatter = NSDateFormatter() + + let date = NSDate(timeIntervalSince1970: unixTime) + + dateFormatter.locale = NSLocale(localeIdentifier: NSLocale.currentLocale().localeIdentifier) + dateFormatter.dateFormat = "EEEE" + return dateFormatter.stringFromDate(date) + } + + mutating func translateToGer(weathertext: String) ->String{ + switch weathertext { + case "clear-day": + return "Heiter" + case "clear-night": + return "klare Nacht" + case "rain": + return "Regen" + case "snow": + return "Schnee" + case "sleet": + return "Schneeregen" + case "wind": + return "windig" + case "fog": + return"neblig" + case "cloudy": + return "bewölckt" + case "partly-cloudy-day": + return "leicht bewölkt" + case "partly-cloudy-night": + return "leicht bewölkt" + case "hail": + return "Hagel" + case "thunderstorm": + return "Gewitter" + case "tornado": + return "Tornado" + default: + return "keine Wetterdaten" + + } + } +} + + + diff --git a/APIClient/ForecastAPI.swift b/APIClient/ForecastAPI.swift new file mode 100644 index 0000000..2fcb852 --- /dev/null +++ b/APIClient/ForecastAPI.swift @@ -0,0 +1,69 @@ +// +// ForecastAPI.swift +// APIClient +// +// Created by Colin Otchere on 06.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation +import Moya +import Freddy + +enum ForecastAPI: Moya.TargetType,Cacheable{ + + // MARK: Network Abstraction status + + case cityWeather(coordinate: Coordinate) + + var baseURL: NSURL { return NSURL(string: "https://api.forecast.io")! } + + var path: String { + switch self { + case .cityWeather(coordinate: let coordinate): + print("https://api.forecast.io/forecast/9aa042dabcaa8424727f3a49b9cff386/\(coordinate.commaSeparatedDescription)") + return "/forecast/9aa042dabcaa8424727f3a49b9cff386/\(coordinate.commaSeparatedDescription)" + } + } + + var method: Moya.Method { return .GET } + + var parameters: [String : AnyObject]? { + switch self { + default: return nil + } + } + + // TODO: Provide sample data for testing + var sampleData: NSData { + switch self { + default: return "".dataUsingEncoding(NSUTF8StringEncoding)! + } + } + + var cacheIdentifier: String { + return self.path + } +} + +/// Represents a resource provided by the ForecastAPI by its name +struct Coordinate: Freddy.JSONDecodable { + + let latRes: Double + let lngRes: Double + + init(lat: Double,lng: Double) { + self.latRes = lat + self.lngRes = lng + } + + var commaSeparatedDescription: String { + return String(self.latRes) + "," + String(self.lngRes) + } + + init(json: JSON) throws { + self.latRes = try json.double("latitude") + self.lngRes = try json.double("longitude") + } + +} diff --git a/APIClient/GoogleGeocodingAPI.swift b/APIClient/GoogleGeocodingAPI.swift new file mode 100644 index 0000000..fb21395 --- /dev/null +++ b/APIClient/GoogleGeocodingAPI.swift @@ -0,0 +1,68 @@ +// +// WeatherApi.swift +// APIClient +// +// Created by Colin Otchere on 05.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation +import Moya +import Freddy + +enum GoogleGeocodingAPI: Moya.TargetType,Cacheable{ + + // MARK: Network Abstraction status + + case cityRawData(CityResource) + + var baseURL: NSURL { return NSURL(string: "https://maps.googleapis.com/maps/api")! } + + var path: String { + switch self { + case .cityRawData: return "/geocode/json" + } + } + + var method: Moya.Method { return .GET } + + var parameters: [String : AnyObject]? { + switch self { + case .cityRawData(let namedResource): + return [ + "address": namedResource.name, + "components": "country:DE", + //"key": "AIzaSyBWzX1_Pzrxyf04oADXfHxqHIEkvAHdTAo", + ] + } + } + + // TODO: Provide sample data for testing + var sampleData: NSData { + switch self { + default: return "".dataUsingEncoding(NSUTF8StringEncoding)! + } + } + + var cacheIdentifier: String { + return self.path + } +} + +/// Represents a resource provided by the GoogleGeocodingAPI by its name +struct CityResource: Freddy.JSONDecodable { + + let name: String + + init(name: String) { + self.name = name + } + + init(json: JSON) throws { + self.name = try json.string("") + } + +} + + + diff --git a/APIClient/Images.xcassets/Contents.json b/APIClient/Images.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/APIClient/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/Sunrise-50.imageset/Contents.json b/APIClient/Images.xcassets/Sunrise-50.imageset/Contents.json new file mode 100644 index 0000000..9871e2c --- /dev/null +++ b/APIClient/Images.xcassets/Sunrise-50.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Sunrise-50.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/Sunrise-50.imageset/Sunrise-50.png b/APIClient/Images.xcassets/Sunrise-50.imageset/Sunrise-50.png new file mode 100644 index 0000000000000000000000000000000000000000..b2cac55b6a5b342f75487a16373868d8196009db GIT binary patch literal 653 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 IH8?u&FT_gT&j0`b literal 0 HcmV?d00001 diff --git a/APIClient/Images.xcassets/fog.imageset/Contents.json b/APIClient/Images.xcassets/fog.imageset/Contents.json new file mode 100644 index 0000000..c528f85 --- /dev/null +++ b/APIClient/Images.xcassets/fog.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "weather-2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/fog.imageset/weather-2.png b/APIClient/Images.xcassets/fog.imageset/weather-2.png new file mode 100644 index 0000000000000000000000000000000000000000..dad3a49f2adad25357f6fbe646442dad8bb02b7c GIT binary patch literal 1091 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&F&8^|hH!9j+@PVMe1>(tbce$r9IylHmNblJdl&REF~Ma=pyF?Be9af>gcyqV(DCY@`?%7^?z& zLR|m<{|{6@3g{mKG5!0l0&T4=3GxeOU}R!pWn<^y;^yHO6cP~?mynT_Q&3h>Q`gke z*3maGG%_`_u(fk^arN-@_VEo2kBCc7OV7&A%_}Y~E3c@ms;;eXXl!ck?(Ls2amvgE zOO`HMwR+Q*t=qQm*tKWxzWoOdo;iQ<^0n(XZ{N9l@BY*0FW$U;_x{V*Z$Ezi`uk61 zbz=)KIc)NDaSV}=e0wlFSU6FH?SZ*rlT@IN%Z9|HH>})-BD`7=2b)+Gw`nA~UyM+? z`F(%&Q`Xac_swtGrXM;}DJPNKWB6?UrJqSQ(SqKY6Ak~)eCPIh*L2DIrd!sXVX1L= z{cC1Jb;m=+p3{KdufZL{(xTejpxFI!dF60>j?Oi;`th~A!?haEqBL6s$~+LL$2QGoUr|hY2SqOE1^y&UN+2nHCy1Cd1$Dy^_*72w6j(< z`={;M{rll-p;Vp&{#6r=;tu&AFFzI0u-x<14hH|5-SW~WtBr3kCj0z89Y5D2uF}|M z>AavL?>~Pip5kP;{J~SJr8(`>?==|39lU%(+-rqw%lgvRq)$Z#$0U-^*w-@_{75qS T99aJslz2T|{an^LB{Ts51o}aN literal 0 HcmV?d00001 diff --git a/APIClient/Images.xcassets/hail.imageset/Contents.json b/APIClient/Images.xcassets/hail.imageset/Contents.json new file mode 100644 index 0000000..e7c9ad4 --- /dev/null +++ b/APIClient/Images.xcassets/hail.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sky-3.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/hail.imageset/sky-3.png b/APIClient/Images.xcassets/hail.imageset/sky-3.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2786d1956960eb37e9aeadb43548c865e83784 GIT binary patch literal 2323 zcmeHI`#Y2g6#l-!7-k16w=l+KY?9m3gj^cdJ%(|M2q`heGG^9HuHS@0654XhB_)!u zDTK^yk}X0miJ_TDMKLih<5G6|FZPE$&-0%5Ip;a&dCqyy4=2-u;E0k`mIMF*HZTLsJW@{mUMmz5Dd^4GfKbHQA3l zU}|Q5(9+8K5Z=c2H#>U=M<-_&S2uzO(aYP%_lRFW;IW|KkmI2zPlZR2PM?X4iXq2R zsBtv<+4#hyWX8GFwDj{AGBUF+UdqYMzw+nRYXyZx#UAh`GQHO z?sV*75!XqX0&iO+&O1X=2G@u(%Inszv}I`SJIb;nGmQMh@*Z)Rw=s(~sr{^&vCDDg zoW<+wef+-CM?CY7XB{&fRZ`2PkN!n+KRvOCx-s0dq2y{ELALc*B;?jgpI<$WoDc3 zeb52Oy0+308Kw>3OmNI^G@y8Ft!*%21_k9rL~WeFLX=&W{uWpaH1Kd+0}G>eat4}4 zo0EWBr+dobgT@2=v_>|-JKc>D8?>x8+{?g0a`mX4?6?Y294G%-koZLE11^Rv7EwGJ zJ|4xo7e2~QkcX|MC%I<>0-MK>A7rOpv;^E8UEVT<&1Na9u_Y?{-K!vX$Twa7b%UA{ zv1iBIqS1!5W`Q4*^MM&NIFT+*NwrWYZrgC2;q!uj1SVQ5lM4%+ubxJ^KquuB@cI?C z_5C8>mwc~x%G97M<{iDoI_k|Vj?Jl2G0ym$kG&TR*sbfI<|=2z*XvXa(+1o^IuC*r zDCeEpfvH#FrF+Vl`7{xI-D>NAd(~S@BPRKG{j2c{LCK;{%OO3ze+Ehi1dK=`K*DN# z`Sb)jk*SsyfVm&zHd!4WFsoQbw0Z#>eT-t88;@@kW)fyn-nYb=)peG&F!s0h$b(G4 zLv4FdPfo!a{}|E@ad1ce@)`_8Hc2FTh}O-KvTFbV`N8j6e<*kq=c%?Iq!;!sbOPKr zz?5M21{~^t;&vkN0&`?|I3q5(w%u4Q*T@IfzcIfz#LuhcQq=;!#c^7NyX=${Razu5 zhlzZWd{34>907)!up~6n=u#0XCtHDWUZGan8>#oZ2Mjw7tMXkW8%IUK z&;u-EjabOEPey$iiaZ;6wp$Ktf*gd0rw_@2&7WDGuMmPFO}r}HTHz`SOA)mL%qtP} zQB{z_;A#}F z#d5!m_(xPWP00|9E+R@tgA}xFZDO`!qi79ZR!WQ7z68r+P&Lvb#c1%|FENtp<#>T9 zu(~UIHf35`eT=+RjIL24VVU}htrVV~Hk_N4*Y!6DrLH$Hfe2h3j{g$S`D3#^o#zbf zO{mn^p6LezKl=h5`6sv3eRl2}QBzd#T`S^2!TRmgwP|$xTR4w95)XV&Y(

#g83o zB?iS{iQ=j+_K~;0F@_Dc2Ia3RrQSU=b-gwrTJOqAbu>LXL^^n=@RP|xTe9Fm)#El| zGm&wFXh9?8l)mZ>&z4uv^K1N?QMog1qwKJmqrbZU%ZT0(?I#j=(2*oZgj%M`%5^h! z@DQ47e@WBj>s9uyNbR4s3!77#&;N`RHq#T^ML6~%sCTp@b2sM&vk;!Bt`66}Kz~n?*c^&=G7RqkxApH${-t|eURc?vp9qByj{ RSM0|ta<(Vf)!T-g`xnm*0MY;e literal 0 HcmV?d00001 diff --git a/APIClient/Images.xcassets/partly-cloudy-day.imageset/Contents.json b/APIClient/Images.xcassets/partly-cloudy-day.imageset/Contents.json new file mode 100644 index 0000000..a4b1ffe --- /dev/null +++ b/APIClient/Images.xcassets/partly-cloudy-day.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sky-4.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/partly-cloudy-day.imageset/sky-4.png b/APIClient/Images.xcassets/partly-cloudy-day.imageset/sky-4.png new file mode 100644 index 0000000000000000000000000000000000000000..af2e43952b549bb1387d54d53fa8262c6d30ba13 GIT binary patch literal 2642 zcmeHI`7;}e7LM8?O^{Lzu>>u#T+)c8mLiCyrIEza_1a5n7h9iN6BJ#vX{q3%5~Qti zs~TyGDy5d%uWC`TFGXm2TXJt*oj31~cr*9ReCM0<&H3egbLO0@csEA~NC^Z003gmz z_Jlo7{RyDxUKUK}Z|{+44Az+h1Oh+uPEGHXQjt!lV*mhgnV%5p^7h!;6BQ{A-V|a) z5GCF>IuH;aA8!y6eksP^H!{#5BKjg@-BJkv*w>9eNpjfT-QDZ|H~w|t|J?zV)_33b zW>}*T+=u{?eWGIG5|ThE(0(vPT1FOnKu-Rk!XcQV5?onDRSlu8p?Ua-mNrsHS5N;J z14GnNv=PSG#MJDVxrL?GaT{B#oxKCj(aG86q^sL0Jb_5^@H&0w?78z7e)aM7^A89N z3JxJ(3JnX7h>VV*#Ky%ZBwkKRPDxGApwcq4vajak=3T#WGym4@J9i5T?-emhN`EUW zuee{ys;aJGKX~}4_HkYP?@t<@Ha_Dtai70<+1%3F_PV{}O=s8Jp5DH9{ewfpBco&Q z$3J|Wn4J1F&6}B>n_pO5T3%WGytcl<-`x5l`17^weTB$a&k?hjaUC{MX*# zYU~Ohz3kHR5P{}Pkx##B8kEJIO~a1ZE5wmoktqpy(L;aBgi zui)R@JkPH^=2Tj&wbN%i)XS{f@BE~=?daiax#@7{*@|i05C_T0#~6UZ|0_MoYl9x{ z3kCHfUJad(WyWJq{gL8iQfb>iH>S6!X+SuRNZfor5Yw|^eWn;>)p7imAwo6CeFo$5j-I%68zx`2$3Fqgv>yc?_pH z$&M#$-|ucmvk=AgR*}V1|GIVv#@{lmesqPe zm|-C9(Ij{7A@z0S_@u+Amzt%OEc>zhrt+JVx4^im+@(s-p@;&A$h{soY(0AN6k5Hq z_eYoALyqzohX}FM{pca$UMJmXVMRB~5`^CQi#- zoZ4Wq7Q4=_f>N53dxU)>#f$`ZHKn8!PMRDM{*qG-0k<8VA zLJxkA(9mNNo`skYNJz-5U#=MiZ(W%yLhDP4;&wT6=OwHp13p)gSMleLFso@fJ-4Ax zy)K)BHo`ea|)Sb1c z2^Ol>HgXu{2G%)Uf8gsC2J6(yD>e<5ns&|XdT}X@L@othfp_ZIJX;n)FR*0{K7QD* z6P6jJsEthQ)VP%h=1-*lnB+01;gHv*OuyqAdQ7rXZJ;qz7Zz7MWIZTz(UeIzM|9Jp zoft<2D<2eJ>NG?e%e;AN<+==o2`rf}fdzjLthB6!gocM5^KParbQ{rgd~AXwX&{(D zhv`Ss6VN{9T*QL~^68w|xyb=b;NOk|&8` zr?p8e@$p~K)KPkA7QN|4Q8SAhYj}<|v+=F9E*?p@>&yk4TkmTlyF5Ttl8k~K)8vxv z)Gl23al_i+rKJ1!{j|$VPX8ISdn?R>-du2Jr}C9VR8KnR!(WYRR9fRs@*# ziahKQa1_B@9MS38@iwWwGOz6bY}jQP-WpM37N_m^MT?e?3NmEIat2QYtbr$rFunyh@57g0s42G%}*0dY3SK z;i!=c)U|r+D19Tm-R|A#O!6nRJU6`Bm(#4#-Z`O~8Iq!Gj=Sh;c@FFgq ztxJt||N6MYRI@zP$c<1BE-E(BZ45&2qA%%uy>2sr*8L$y46SI87Wq@bMRM3Tr{RVU zX1q-4M9oFmN%WjPO|pDPk%=x0(xjoQO^8ZT!zU~G;v^xm;iFHf=T1o~S%xNx%4Z~3 zm9wh`fO1XCi!}E2wvfUuS8Ey4stzP0aYFD>%0ql$ez~DGEjXUXZRWw@_%ya}73e|1e8c++raAk}Xm%K&o`x%^Zxyo83&8U9B-| zGJ{;5Ps$*SA*tQtj&~LdWTvS0QF-TQ%V)gyc3joC&r$9^^M;7UXAbuAFRp?ph1y$O z8f%+^5F`o1iYj6pbTwe#Jk{jZMpzLQYR}xx3m7Y}*QvqeglB$N(p3I;jZX~hilhYL UF&a$X^3PB1?BHf!i}gwW2loDnegFUf literal 0 HcmV?d00001 diff --git a/APIClient/Images.xcassets/partly-cloudy-night.imageset/Contents.json b/APIClient/Images.xcassets/partly-cloudy-night.imageset/Contents.json new file mode 100644 index 0000000..3868788 --- /dev/null +++ b/APIClient/Images.xcassets/partly-cloudy-night.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "cloud.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/partly-cloudy-night.imageset/cloud.png b/APIClient/Images.xcassets/partly-cloudy-night.imageset/cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..a1106aa9b8a17f6f6da54c7a7918f74f6d63f4cf GIT binary patch literal 2655 zcmeHI`#Td18=mtFp;qrEg;X|grbJE+V-B0s+K3#|GLjrKd{?!cCQC+`vmCdvHRVi- zqJvLzETYIM&1eo0P0_3G&-kwQxvu-Uujjd*U+(*d`?-yCvQ+@7fB*o10>%!F-{IIl z07~riwaIkR4oO5O)%*iK z0zgb$LQ+av1}F=XlULZKsHD7m4|wmszaUVR{i+8Js;O%n(mZ_Rs1^*a{r52)gzoVZ zdMEV_P8k{*o0uZa%q>usR%mM*TRRNa-oeqy8FvOxaB)5B=6=q@)9bv?1>!|tlAr&j zfXjhFA)(<{Bgm0a(f_%2{RZV`Ok8{dHStyw?RN5=6nbjf-Smu1MpkxCZeD&tVNr2O zSvix%uH%o)Z+d$B`UeKzz8e~T zKQj7ZY=*u=V1D7NaB*pQ<=g7o_w|h*qRpSbwzgRV+DSWMu#G{ZTp&=s<|EV&Vc?aRaRSE07%$IRPx-b zA6LVlo9+KLZM(S-U+bMPa%EcsdGq=sQ>ut@RCC=Ul>MqreLwe3Ak4)>DMGl-yh9<{ z1{^HcS3U9GU(H*)cB&?!!%XgC)ldjm#s5@-tsz!Xb9lO~Vt(oT^16nUt;)q$3<NyB}gw&H*EDH{jrB$u-VMt)iDvW1a z&nW6+FhWe-uQPwWZPJ>^ku+a`^;pMNf!XTXI*Xz?VCy-zPsNhD8#t4~6o3|7-U{r| zSEF|~($B3q3$Kz2$YUI|c!57}WKT&|^stItc?v$IiMx*7(8ODJLdG~+$CQ#`-z`hB z86f4nFH3ddrn=964-CdFrJYbY zvLiDLG&S#T%Q*z4=Q=j2l|0c22TXU#AjNH9ZG+kjp#-7d*Q9R^3!l$D1ir> zy`k%JZwb_6r*-6t83MMj{vPh9Zi(rxXN- zja%tE`_^6;y=aZ?J=pJ#71Xw9t|^SztBGhGc1U+?!5_>;I$QPwV=c#g$sutxPNn(yvK`K^O zoMGUM9zJus38e%9s*?xJy@|{lSiy2m(=(eiO^awPmhy3zeXIp#m~b@VU63>uu9H-g zZww!kMTRe(nT5nsSHZiQ;@eXR5V-@{IjSy5g)t0A$>yW;6kPK4m|f0pz!Kgl2T(o= zlSjpB43R}|#4jKdvyOY%W06yrETjyIU(Cd0f!XZ=_h1cihOAKNxIbLU2?vWGcy*@I zb&@@{=D&CRYnr92{gfF*=n2x286VNmII;EZNyl_#=bT@kLYT3|R5;{VLlHgf4Tkzf z22^*U`gRcdWzVuZiYS+o6_t+)ek%8gjSnMr;Eu>oPv|biK3sq~CZ%tVaQH9E+Pi?& zIhGVd2!EcyXyn1ogDP-7uG^yftvdaydaQ}vM8+D0q3sE%t``g%8hWF`pqJpSvI*o- z=dKU3rFqyck%MZ=@j;s*2o=W3=YH#@d88?jMUoni8&bKOf)$!gT|8dPd!4CHF6S6G zklZ(TFM!PGMYsAjwH8WNa@ZSYP2ou$U|;h!mANr>sxaGE|ILFSwEB$DM5TSjTI|p} zVhw%3)=uaLmKWmx0SOzE7XSbN literal 0 HcmV?d00001 diff --git a/APIClient/Images.xcassets/rain.imageset/Contents.json b/APIClient/Images.xcassets/rain.imageset/Contents.json new file mode 100644 index 0000000..5ced6cb --- /dev/null +++ b/APIClient/Images.xcassets/rain.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sky.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/rain.imageset/sky.png b/APIClient/Images.xcassets/rain.imageset/sky.png new file mode 100644 index 0000000000000000000000000000000000000000..f4d91ca84f5ca27aca8d82c10caf1713cb027996 GIT binary patch literal 2669 zcmeHI`#TegAKoRi=JpL!bImtn%ZP<=W|rkrwj{Zf%bc<7M7dRB zC_;4_)fpBg6gg>WN-MW%E{T2hXMCUMe4gk1ywCf2KEJ&0FK-UXd)93sCUp{w^w7-6U|56Tt@xg^qvl6m80_6qkS`06>TL3&2qABHhg+f`<2}c_$pF z(Zi`x06Lv+elk8LDKeZAWu8EdE}wPK1^_^PBsU+tTrS`I|9AdP;Qu`VJ^sM*riU5Y z5f5(w5Cq<$08xZ)g()eksH**Eo4ST3TxT((7R1BX6Ab= zEU|m7tZnw$+S&i+u;1}_+ySS9&iF$v1XrS)yN4&q>xj3Huiw#tz@Xre&|_iY5s^{R zCr+M)If8fQ-!B<1WBd_0# zj*b8GZsNV@!{kTt)ThtWUnE~=X6NP?q>JBWOUo;(Kh}P(Z}@-#EC2waOK?8mvjZ{H zRd8%r1{5qT>rsAQy+l%Cs+Xz|ypG-}(X4WhdCR^k<|f%&2MJHr$HjN_<59xVf(y5- zqwwx`xkIlg;Yw!47mwdyu^gR8>X;wQn!#`}?PPpSEFXT|Dk zNmJDUhuf!r4*1%A*(KIsb7iu%`__qrv%OT;Zmm?Gjoojm`vV=RJ}g&G#i5acox$z6jjc%ibUrO?z}vjRTIvQ#kL`Y5S37WLpBTD^6c~NCQV5$ z<_Q($kvy6^g$}uH()4qriogF-)T73ddQBn|lpOOLNx#ulD+EZ(_htmcaf>qPK`AluS%)Oa{p(z3-!OyOm^_7Q=Z5l)pf@P{~6Rm0hEe@T+K43x@EG;>Txsk+5b!KIu+7siVIi7Xt20$uK3#(eDNR+MA1JQMb-eLmx>+fBxH+(b5C=TB zJG)~S8R0n9d#W=o?{%FkLv0t_YDiV&o!FXMox*$ut9_V?S#yxI!EC?zk!tk1TfE*a zflT4#W?pyzniye1t3i!U-e%M~6Y`jk(JOyZR8b{9(4YQ>O`sD*mMb#_#+*MTLZ37! zY#^1X4Z8@KR#{GB0j@TXfy#PX!5FbuG(s6^0c-4)^Sxcj;Dl-4u!~L+Rus2q{D>@P zE6Rc2!MSkt1zcte^M^%Nw|}MUtbJIgli~K2yzdxNHR%j=6w?n0JOT%$F{g?@Zz0_g z5x-q%G$Q0N26W)G0`OW?;!#in-n2(uhv_Tr&=C45jPaOzn9jt=vqQ0OBg%HgxMCmF1Tld$#_iYN}Nl<5NSEz>@guP>UvYq$Q8}o zrNfyk_u{#5c~~Y$^c#;^7Ti3>(hrae_K!qMV(FizuYFdMPFj(B3JuS3?8cE*;dD>- zSnG1SS6hJ6k{?bIr=a(M>SgE|Xh;qbL@g zIoD^L$1v!thV~Q@;K4i0%b(7D>_>6P!>JWTgIqSdrp0~5MP_L1b=Kw5V4>kbuH}y_ zAF$<=2gHH$(VpvPIOz}a8mJQMwj8`$?n`-N2Dn~z2D)^=A@Ntq6Yw6+jZR_b{|6mFmyQ4c literal 0 HcmV?d00001 diff --git a/APIClient/Images.xcassets/sleet.imageset/Contents.json b/APIClient/Images.xcassets/sleet.imageset/Contents.json new file mode 100644 index 0000000..491ccd8 --- /dev/null +++ b/APIClient/Images.xcassets/sleet.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sky-5.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/sleet.imageset/sky-5.png b/APIClient/Images.xcassets/sleet.imageset/sky-5.png new file mode 100644 index 0000000000000000000000000000000000000000..375264d9c7564f84342dd1209ba0f20dc17d2017 GIT binary patch literal 2544 zcmeHI`8O1b7oVsw_OERQ6Q040eHmo34Z|!LV`f5;EKQ1$DKnNQvdmZ>ifODpyNQXS zY|l&CN+DbI5GAyro-MLgzSH-&?>XOp;Cs%y=iK|b+qvhS&pG$pbRq#G2~-9G002oG z7EKah!cP?y7TArMoE-rOM>yapqN1Wxv+gs3P>hZ}5di=ka{j3Yx|(*C1xYZ&$(unA zKg);;xI_g+MMW8&zYrP`6hNmMhF=Q4v1~195^5&8Qk?ep_XYj`$UhAHA2Co2pU4%g z`;kE+kO2pTgbyA%EFvlf6qk^cl9rMEmz=zUq7n$KtfC4zqNc9#izZZC2L{*EH!w6Z zHZe6rm|IvLwL%`Vwz0LdM>#m6ot!aP9Nxv%jo?lsk&k};g5EyiZdiLD; zkWgCKg>d@COA!oaWK?v_ud$couOuWUC9_h~(tpdy%({9lJBM?fo0nfu_8`-vdv?m^v3VPKjy~>&~Z@{30bH9X+;J1Q5 zgVu)W6B_gCxiRO{bb<{uTY^y?P2n*1GD>JM+&J)o^rQ`nza|CUq|5avI<~gIlTWfN zH)sS$($or}FQWc`WF*V0@+G-;Pr^L`e} zEWNA!bnH{CrWKEJq#L)0tS`D~fZ|B#md>7e-JHL+G=S!$c)*jH;1#o+8#(%?(@5s} zDi3qT4hE~oi0~PSPCd84)bV^HFH_n8+MDQ1m8r7|HPVzaQoSzbzn!U7du8uyhL?61 z=Pycc52vnJqSmP2L05>P-N{jq(Cb5m2vLSo70BQgQ9h6uvH%n}-6ET0->Zk+PE?41 zv(IWUJIK08ho*J$kFmw`FkWH9j5B`kS9N9_-&aihVKu`H0dk=lbLOj?6p_B}e7+o~ zmGvCEKv&@Px(~;drKhmyZ`W-kYL^Zev|llv z^L|`CJRh5FU#~Nu45k_)3Wq?k89LFUCx<5-*Jh*ny(h)$|kX2{i z^dK5BoTS}5X$?}Ad^MOCNwDX(f^Iq5n{>Pd znD@h%m37Yl(XjMJO7X7iX(m^8iokw9h5tYwHJ&hPERe0WmI3l9yR(^nA|MOl!OO?F z@dGUK?o#!=1A{lox74KOGo?vj(HUWU<7`zMMG;U_K`fNgVIt9dp#{f9&!e>k{py*O zFV%*W9Y0w6qRSPf26(25mGGCH0c{kZF~{Mlc<=`j_*$I|TZ8Utm^*C`W{b?$b#X%g z?daLiqn~Z@Dgaj=R~i%NcwRQa@EDx7(TP$@g-JR!PQeCQ5$!&(FxJc~v<5hCXG{K^LYei+i)(4)nb0VPcIQS?18)geU+5i9m literal 0 HcmV?d00001 diff --git a/APIClient/Images.xcassets/snow.imageset/Contents.json b/APIClient/Images.xcassets/snow.imageset/Contents.json new file mode 100644 index 0000000..78913dd --- /dev/null +++ b/APIClient/Images.xcassets/snow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "weather-1.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/APIClient/Images.xcassets/snow.imageset/weather-1.png b/APIClient/Images.xcassets/snow.imageset/weather-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1e423f3fb369918a2a8b3c22400cdcc93c6b4a67 GIT binary patch literal 4062 zcmeHK`8O1d*B|>>BNJnW7F#pJ!;mF}#=c}5lWbvRo5ns_ifm&YQD`j5G8khgW0x{b zQ%LsgSqq^O>M2F9=g)Z0`QCHx{hWKx{o$U^J?AcIw$`SCd=NeW03c{?W`sV*xc?N$ zacuXOvVI){2f@G`0|Wx+mTi`fUEW|bCjtPV>HeRx`NSkm90w(C89Uyx5AwMcferNr zL_|a=;R5l58`xlPrJzvX!Y`K~004Wl?G=pi-@kv4^ZzIRW8nV_1BDP+%WS4pNGK}6qS%Fs%jdV7qzr? zF6ruDMj03ynV6YdSYENRwz0KC+hZKAIXXGJxL$X2_rQAI@bdQY^~2r7`v(LD1&4$Z zZiR(MMBcs=6@51*HZFmfn3SB7nnp^$my!7(D?8^QIX5rA;8Ee@qT-TLN?CaYwUSm< zT~k|E-_Y3fq?z8*+ScCD+135D=h^dK#tY_4)~nZj{ci@}4h@ftj*U-DPEF6u&A(q* zTweXSwz0YW`OD7k-v0L=|Nc7o{paxLYoc8=0Ki{wZiK>sC0LC6?h|3fJUdenF})Au zI~y9RaZa>%#u2$=ZJ!!kjw&1oDy_EcssxqQzB4}+)YVW%T)eyjV#4e!cS?GiBAArx z6#l+GqOwSO??6BB*@cSu*hl8RQZmhtXi-#f%|$;7Oi>Pdzj3;Fh#L zrLtxz=?rOT&%QY6{#n=Wm_XYyIhIY*XHMI&zjgC~0KQo@DRL?W) zxX%4+TSld~LB^N;`32vm_I6|R04L#m!u~wn?@VR-@E}&?j-=ohcxoIyV<5%xatJ_v z4tH_Qpox=|jk3aIi)4vNVJ3&mVaZNHtR!&$Am!q`nVg^qWWkzBF5~p!1*Ldsq{}M^ zKfwkFIPlT6K&Oy}43AG8Ck$P{9|-wx%c>G*&PaUVn9rLg2w>Rg5}A)gu{KI8CB4-N8>^ZHx&2R~n}Xy)X~(<*v?Jx(5xukijl zPcF=R9ubSR3+cxm)F#cSkz|m+rI;7@kOofg%<*B!LW@xVeNpvsIS{MO#I-U%$dOi& zqkQ1WRiw^f(|{!KhcpY$Ilc>C@Xx>Q8F|W@GmYkF)O3BDk%Lt5JyBCG?8nEF;OzG~ z@klM7)jdO;_2Y~zF5``Fd&2YizVyS2xow7s_#dmXpL}c@_PF}rWtCmcD|^kuLNRwr zga0n*b`$hwo`i&}89)mjJPT#*wzTKT{o~ZKGraeAe{+83f_uTy?~{nvH;O%6exkIDcVq&4Mg~+^zNv!xL~za z6DAC2*PAPjKhrI(B#FpyG%hn~*d8Q~jl4gQ<>v@-HQ3Fg+Lj4Dcv?h4>Q#=Zf;^>- zd7{UvBqJDO9JJ~!QVN!%r&;)w7$ShVq#nPbYNSfGS7`zfvdh@@+FU?|A|_(wAIl@U zsBeN#7edE_?+7b)W{$3(j5Zl1PDmZq{#Q5%nYqFP*z5N5OG}b7Jw;Z84T)lQ z)g4_>AG=i|6IZl%HgzGh$uF{d9uH{zOv9C;{fMm?#NvIZ)i;^7@Uam+f!u8>rdg!- zstt8o2>)hY&9&spxADPlwOaxyaxN-lNzSwyDta@nRW1+`Xgl9&$s~(3Rh+Wz9~V}v zAz5^COp1k%j6-hR@dY40c6>kP&FWvZd+bvi}&MO zr7%LX!jF0qEqeGT*TPj3w^ls@bjYeYbcAri^7kI z8CvM_wx8^3Es&@czn7%+r6|K`YtqZ-X~{FyLvHfpL@m0{(@S?}C-U6xmF)hh@Lesw zeNdeyS`7X>-C=5C^9+^KeF6K=8kj5%t(&&2_D^XInUXMAcXcGZvxh&CQJbS-!h2`) zze=Fj@l9gaEvbX?wk_<4&L)jb9p{dJwd=HMt1uU_m7giujf}CrAY3*6T%FcHHO81B zn_>~qZ7I_*68x_aD|URzjUAtfMzq=iv#qGp+?GrozYd+f^Q744Cd4R-x|#IqiEd#J z1u|MkQ4mj~5R_snz`6$rGRBd93XMyRFUi0Rd~Q-}$w-cBWS@ecW-u4gPHcE*J+i1Z ztN>FZ*#w$1Fr118=-b}oFma<~3*nuW$b!h1-MFfd7h?~6AYCVyLo!xW05aNDUT5z~ zsr^wFAgfK7GRBtZY8~RJ2(ss;OUdpP&0<)88WtR_G`gP8pUYiT$v6~y`iv6E-sK)^ zCC88Tul#uijDT6c>O~L25&gn>aQWV?YxS76v-cG5)DxGvG{b0T;^d}65V)OBrTIXW zmZX8#K$-92*>a<{V@LPB`aK*;dIleL!Aj^$TqV;!2py4E(@F4<9Zd}tb)m_!o7Hs* zq46s?aPnhnvx}j7h=YCq<#q>>Z>hi$l-vV3NG?wpfc(T!QVrWt85q8R4gMdh2&bKh z;+4gv_4pi&MU4I-xq!a@?11(w)~&BJh#!Ypcr|QVm$1)H`;ceuHQdX^t^HD za)|k-^;6_`tzq>T4Vm6+pqwS;HE>igUc}&bOOft$@?|T~uuR+*Flt0y!smz2kF!wJ zknI&z>4x$&5uJai5Y@!bfWTKoWH*t_ZXjJtK-tEy$sVLEolnokUhUmBPrh2p_;8VB zi41Y|yl9WDyxSif!%ycXRU>uG@kO=51597=tFIp6iJp+b%yIYcjItMZe{~bWeS#Ld zZqGbFs}>MC;J)BeoZGC3>o0rBwdedP2r;+`t7LA&4)1CK{|(UPxI%OiWW7Pw`o>)# zhLq@emFoA_J@VupeCAO~Hw<>y^LU{DqAuH0Z15(yLQCx5b43iF-ns-&rNJ6-oi|Ln zEkT~{5uPf|<`YZxqmKPhFoI=RtYS%8$h6MOStsbBq}yB7(T8{=*#e94(vu`kPJ&eV zvS|K8yTR8fm?0hEcz7UWNH^7!G$kzCRs23258Rbtu`h8T-iXBeK%70}rAfDeAL^*j zqXpxI(6a1iG>VWeVV+_$XA4LIHOj=5lj48O2`|}`G?$(v=$VSd$J(}>AijG-9T9D;&gD9l*hf1_lyL{ZrHgR(V7 zlUN%*3O+Du_^mn1EY5GPtMz{eGmMQqRWm1hwi5fwBl$@VeIt4im;1{d`H0D}7D_BM zxFy>8SFLEWE6HnrOo`+L4#m}L^XYZN&?A;QaP$(LI4}&-JlpgIPK_Nw%{Mt}+O+)ai zHNXiZ0cep#gpA;9hGHb|Dr6pHn2P^6OO%5BaREwi#j++~`3i{{Lc zk^^y--YiFEc!~VVk(x8tXaC0c-1m9Td!F+??=R>4avs=NU6O<) z5E2H0z#^g$F{rqNq?Ggl8QFs{xkK`BgaQ(UKCE~|>8P^GF;z8;`tcJQSe&Mo_9-1b z{nG}2;Ln^jJa2Tt*yN(AxrODQR@OGQcJ_q79Egr2GUf6W>QyIa7uq$~>o?roJv_Z` zdi(hL`3D3B-3kc}3y-)R8AXqdxpO!6Uflf$591#_PGBT5laf=?(lef9W@SIm$<50z zC@d;2DJ?6nsAN@Dzo@ONZ+zL*+|v50t)2b4qqD1<)5GoU>mL|=^LA+X-N^e7qhsR} zA16OeedbO7!~Y`qI`iLe-)HCM7k(@*E&p6uU0dJS{I#{cvwJ*rts4Lk5j8VDPkUTU4?q4f1Lg}HU{F%c5pI}NF7ixLL4N3B(#Sr8(=ERkFPx$sBXFotAriGskoC> z4hU(BL`x)@bUK$H?WwAnG@rSj@`2}&uTRtN)Yb+p%%rm{vZnuxRPnhz+#mMmTjzCPH^Ntw@iP{ z(`55xlZxLAQiGm}OARh#B4itfDoWjk^{cig>%O4LD0r!FC@%oDTAn;m6mdiysj@lhL@`VH! z6soYiJw|%*a?rCFEde2l^tWK+{E4v%zcL(JW|u)IKkT! z)DUFLbCGt6xR5(M53-peqM42&sM)f_5UAVJyaWUhs9}py`2cA8USgTE78YxGcG3Hh zL0P|Tj!jnjBxtfQp+%IIWN;JfJC=WB4!E21rnyKYqtdAWp!4ay8G^lp0lP{s-VU-8 zN-X4Q0CrhYvtcvV*%W(1>$mRi;O_F^Gl>N}i7r#SxRs}`mc(%edvCGqC|HGFbnJKf z%V)=N>v=Kt5H68@^lR$7G#_(zK;VrrjGf2reyEN-A9#z{Smfsu~Be+TTUn#Ypf^J#XrJspbi`tPL5!<4dLXGW?aT?m7m6GgVP3x9B4~fJN zwIEvPT_Z2B{Iem51w5z`oaM=Fj)UNY^i0h)Jx%LK)*sT>xCzw9Y{SiP z#D*r>0S{>{bP&k~ruE(%(>_9}+>zx+k`jT0ReR4RMd2WIXbS~NM_uu@l(R`L(nQ{Z z>ia#O(99R(t1~*>jle_tCO5-iJ<+|;OzuF~qqz48BMPXGJ`93>NLwhV2U_nr=l3-0 zjWzllhO9I~>&j}!cKV&QAP)JghT_U3v%+>~e!4f;3{%AN@3n%i{MFZ|-N9e^5qIK9 z_ENiJd*cd9De&vinxOGw87+@yq-wq=f0#*Xx*#YDvRPn;x7}f4Mpw>(|I^LYsdA3c z7#-lepm>{AbS))K+L_k&2$DqIn5w}N1{U#t{;@aIY+{EkSQ|9#97lA>-gwpciu&GLU*(rknlEv+y?CcsxCpsr2oX6TJdS68B0P z0hX-xHE?&>y&yAMv~tbD4S1>cg2+P_Qa7TjMC*?0V1|LyD-^@8_j=XbeFI3u1TjHw z!!!+T?J_{94R0zaZLffT1XS3@zkIHUJ40TkA~@zGnH?#cDT~MkVY#Im7j;hHW)o8R zio+ux(6XR-OO0(sk_mv9SUlG{r9&g%#c{zNas3YqFE5|3d;0h$C_4qMwy0$$^&>Jz zg?tOfr#(dd)KcwFQi_^r3BNS$i5%4t2D+|Pfj)2>rVQ&Zamoz^>DMUG>Z=?yT)MY8 z)Ud4}LzbsVC8dkwRo%6QGBmbs0p1lNztaW&=MlcI>JDza%$$oC^-xZU*0RUFL~Nvo zIRL=^o$GXBy=)2Ms2*M#zw};}SL|=1l(?qri!o>EOKnTJnKMr`JC6vR>_zk4{c0GK zT5*Tg`;WEfjUQ%Qwxj1qrcC-v^w>2WV~Oz{D<=I9Cb;_#25aeZ&sfmQjGJae4T~(KA&^$xrt_`h5~$0J^%n9fHl&yIMS$J z1aThK@3T*S9tkH=7i$RufhOm!&mOhB{zkS$0N_~bF9P3H_$eI?#RBzh0`Y$Cfx(2k zZh+w6U}dj6-b5FIznik(U5}iv+E4(1qu0#XQvdMq@M!-({FlJLJpoDjz>gyjUji*m z@cu_Ost}a`W<^7Zes1 zmz0)KUX)inB)}O19S=jIm{mp*-FFaNdr;2oU>S6+K=%gGp0<5L=LWBRR%K73nLA!c+%MIbwM~^AZZPvSAD_<`RQ7>77 z4LYZpL`aP}Gb`N@lR{PDkM79ELww7bYR`L>*(=n-ME9-1x80-8aJxeJqL?l;IMm|6 z#L*4Awl1TOm;K&fu%X@H>QL0N5*Q*jX0RT{hL@qhlI7N8%d8HBsJ%O7!Zll|NFCfF zMM>ie*}jdV>TpwnX9DZV!V0PvTn3nQBF8a;IDNF<|gEhKJUm1D?Q zO%y?b;pVER<0 zL3A_tOe`5rnxW4iNP}}~SzV`q4`zzeIK&MVz;wrBjJ>sNBRAFWOJ<1)WHiLF^LlQQ zv$*zKvv<+$+N8cZYI?8l+Qr1)@DM%6GKHx2K^V#D+_PT$HQ~Kuao&KIHmtcg&_3AA zmfMaYXNRA4;mn}15jnjyW@B1c9=}~Id`wgP@>kzde~$vY84=PgPttx&5kGXEdxpc$ z-23JWNSBWaL(}u-l_jr_j~XnX%H)UR{G#KT0_cDYNX_J&_o|%Q{f$MKb4B*qmu~{q zF#We^lr+g(KRPEq(5{h#@0oZycObwY<@lngK`lI$+} zEg|DWpo5Epqm8CMrLkR;f3!Yj0Pd*6H+r!&Ir(+C(>Q2sWt088a%JmMknIOIx8_s! z`77J5S*Ol_nnG#<2?WjE>dM=Q*4rblBc9uhwy{~ER88tzVrgU;OiRQeg5gxDk_&ta zkEeI?vR~#D&PJetdFlhIa>-yr${+8D?>{|5yCPiR7s$|LYo;`*}uy&A9#$B*kR-MpTrZL&47R zD&vw3jNIW*=)G6dEdoF+Mg6#ytcryXH}fz^l2fRFM`2=*&H|Hu%x0HD8tb+t7;30b zqmZS#rtEoHiA_F+jLjZQ|F{G-bDpb8iSpv1i-?6r=Y$^&+^vQ$e;i**gM`gy>meC9 zo8@4#tl$8wc!$eM#0;B2%r8_IMknnHGHg)_WE?DXTOq^5pQTf-9i1=dSmHkgJXhLi z-e3~ju~Te$0P>(2EcHTmR+_VLe>MD~o#a2Q zh|~&iP~^oKZ+ma8*6HwFRc(Ee_fZtSot1m1%#gql;?HxR3dhy`AF3*cJkGG%H3Fr0>DSB0>YM7- I=sLyx57il{yZ`_I literal 0 HcmV?d00001 diff --git a/APIClient/Info.plist b/APIClient/Info.plist index 40c6215..4f663c8 100644 --- a/APIClient/Info.plist +++ b/APIClient/Info.plist @@ -30,11 +30,11 @@ armv7 + UIStatusBarStyle + UIStatusBarStyleLightContent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/APIClient/Weather.swift b/APIClient/Weather.swift new file mode 100644 index 0000000..300694c --- /dev/null +++ b/APIClient/Weather.swift @@ -0,0 +1,29 @@ +// +// Weather.swift +// APIClient +// +// Created by Colin Otchere on 09.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import UIKit + +struct WeatherList { + + let day: String + let sunset: String + let sunrise: String + let maxTemp: String + let minTemp: String + let imageName: String + + init?(day: String,maxTemp: String, minTemp: String, sunrise: String, sunset: String, image: String){ + self.day = day + self.maxTemp = maxTemp + self.minTemp = minTemp + self.sunrise = sunrise + self.sunset = sunset + self.imageName = image + } + +} \ No newline at end of file diff --git a/APIClient/WeatherListViewController.swift b/APIClient/WeatherListViewController.swift new file mode 100644 index 0000000..6023244 --- /dev/null +++ b/APIClient/WeatherListViewController.swift @@ -0,0 +1,41 @@ +// +// WeatherListViewController.swift +// APIClient +// +// Created by Colin Otchere on 07.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation +import UIKit + +class WeatherListViewController: UITableViewController{ + + var weather: [WeatherList]? + + + override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + return 1 + } + + override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return (weather?.count)! + } + + override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + let cellIdentifier = "WeatherCell" + let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! WeatherTableViewCell + + cell.maxTemp.text = weather![indexPath.row].maxTemp + "°C" + cell.minTemp.text = weather![indexPath.row].minTemp + "°C" + cell.sunrise.text = weather![indexPath.row].sunrise + cell.sunset.text = weather![indexPath.row].sunset + cell.dayLabel.text = weather![indexPath.row].day + cell.weatherImage.image = (image: UIImage(named: weather![indexPath.row].imageName)) + + cell.weatherImage.image = cell.weatherImage.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + cell.weatherImage.tintColor = UIColor.whiteColor() + + return cell + } +} \ No newline at end of file diff --git a/APIClient/WeatherTableViewCell.swift b/APIClient/WeatherTableViewCell.swift new file mode 100644 index 0000000..4fa60c2 --- /dev/null +++ b/APIClient/WeatherTableViewCell.swift @@ -0,0 +1,29 @@ +// +// WeatherTableViewCell.swift +// APIClient +// +// Created by Colin Otchere on 10.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// +import UIKit +import Foundation + +class WeatherTableViewCell: UITableViewCell{ + + @IBOutlet weak var dayLabel: UILabel! + @IBOutlet weak var weatherImage: UIImageView! + @IBOutlet weak var sunset: UILabel! + @IBOutlet weak var sunrise: UILabel! + @IBOutlet weak var minTemp: UILabel! + @IBOutlet weak var maxTemp: UILabel! + + + override func awakeFromNib() { + super.awakeFromNib() + } + + override func setSelected(selected: Bool, animated: Bool) { + super.setSelected(selected, animated: true) + } +} + diff --git a/APIClient/WeatherViewController.swift b/APIClient/WeatherViewController.swift new file mode 100644 index 0000000..d8eaba8 --- /dev/null +++ b/APIClient/WeatherViewController.swift @@ -0,0 +1,241 @@ +// +// WeatherViewController.swift +// APIClient +// +// Created by Colin Otchere on 05.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import UIKit +import Moya +import Freddy +import AlamofireImage + +class WeatherViewController: UIViewController,UITextFieldDelegate { + + + var forecastAPI: MoyaProvider! + var googleAPI: MoyaProvider! + + var allWeatherData = [WeatherList]() + var someInts = [Int]() + + var weatherObj: WeatherRawData? { + didSet { + // Configure view + self.timezone.text = weatherObj?.timezone + self.currentWeatherData.text = weatherObj?.dailyWeather.data.first?.summaryGer + self.temperature.text = String(format:"%.1f",(weatherObj?.currentWeather.temperatur)!)+"°C" + self.sunset.text = weatherObj?.dailyWeather.data.first?.sunset + self.sunrise.text = weatherObj?.dailyWeather.data.first?.sunrise + loadImage((weatherObj?.currentWeather.icon)!) + print((weatherObj?.dailyWeather.data.count)) + loadForecast(weatherObj!) + + } + } + + var cityObj: CityRawData? { + didSet{ + self.status.text = cityObj?.status + + self.loadWeatherRawData(Coordinate(lat: (cityObj?.result.first?.geometry.location.lat)!, + lng: (cityObj?.result.first?.geometry.location.lng)!)) + + self.city.text = cityObj?.result.first?.formatedAdress + + } + } + + @IBOutlet weak var weatherIcon: UIImageView! + @IBOutlet weak var weatherIconIndicator: UIActivityIndicatorView! + @IBOutlet weak var currentWeatherData: UILabel! + @IBOutlet weak var currentWetter: UILabel! + @IBOutlet weak var cityname: UITextField! + @IBOutlet weak var temperature: UILabel! + @IBOutlet weak var loadingIndicator: UIActivityIndicatorView! + @IBOutlet weak var status: UILabel! + + @IBOutlet weak var city: UILabel! + @IBOutlet weak var timezone: UILabel! + @IBOutlet weak var sunrise: UILabel! + @IBOutlet weak var sunset: UILabel! + + @IBAction func unwindToWeather(segue: UIStoryboardSegue){ + switch segue.identifier! { + case "ExitFromButton": + print("buttonExitToCanvas fired") + default: + break + } + + } + + override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + switch segue.identifier! { + case "ForecastView": + guard let weatherListViewController = (segue.destinationViewController as? UINavigationController)?.topViewController as? WeatherListViewController else {break} + + weatherListViewController.weather = allWeatherData + print(weatherListViewController.weather) + + default: + break + } + } + + override func viewDidLoad() { + super.viewDidLoad() + cityname.delegate = self + } + + func textFieldShouldReturn(textField: UITextField) -> Bool { + textField.resignFirstResponder() + guard let name = cityname.text else { + return true + } + // loadWeatherRawData(NamedResource(name: name)) + self.loadCityRawData(CityResource(name: name)) + return true + } + + func loadCityRawData(name: CityResource){ + loadingIndicator.startAnimating() + weatherIconIndicator.startAnimating() + googleAPI.request(.cityRawData(name)){ result in + self.loadingIndicator.stopAnimating() + self.weatherIconIndicator.stopAnimating() + switch result{ + case .Success(let responseData): + do{ + try responseData.filterSuccessfulStatusCodes() + // Try to parse the response to JSON + let json = try JSON(data: responseData.data) + // Try to decode the JSON to the required type + let cityRawdata = try CityRawData(json: json) + // Configure view according to model + self.cityObj = cityRawdata + } catch { + print(error) + self.status.text = "status: Fehler" + } + case .Failure(let error): + print(error) + } + } + } + + func loadWeatherRawData(coordinate: Coordinate) { + loadingIndicator.startAnimating() + weatherIconIndicator.startAnimating() + self.status.text = "status: lade..." + forecastAPI.request(.cityWeather(coordinate: coordinate)) { result in + self.loadingIndicator.stopAnimating() + self.weatherIconIndicator.stopAnimating() + switch result { + case .Success(let response): + do { + try response.filterSuccessfulStatusCodes() + // Try to parse the response to JSON + let json = try JSON(data: response.data) + // Try to decode the JSON to the required type + let weatherData = try WeatherRawData(json: json) + // Configure view according to model + self.weatherObj = weatherData + + self.status.text = "status: OK" + + } catch { + print(error) + self.status.text = "status: Fehler" + } + case .Failure(let error): + print(error) + } + } + } + + func loadImage(id: String) { + + switch id { + case "clear-day": + self.weatherIcon.image = (image: UIImage(named: "clear-day")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "clear-night": + self.weatherIcon.image = (image: UIImage(named: "partly-cloudy-night")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "rain": + self.weatherIcon.image = (image: UIImage(named: "rain")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "snow": + self.weatherIcon.image = (image: UIImage(named: "snow")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "sleet": + self.weatherIcon.image = (image: UIImage(named: "sleet")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "wind": + self.weatherIcon.image = (image: UIImage(named: "wind")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "fog": + self.weatherIcon.image = (image: UIImage(named: "fog")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "cloudy": + self.weatherIcon.image = (image: UIImage(named: "cloudy")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "partly-cloudy-day": + self.weatherIcon.image = (image: UIImage(named: "partly-cloudy-day")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "partly-cloudy-night": + self.weatherIcon.image = (image: UIImage(named: "partly-cloudy-night")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "hail": + self.weatherIcon.image = (image: UIImage(named: "hail")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "thunderstorm": + self.weatherIcon.image = (image: UIImage(named: "thunderstorm")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + case "tornado": + self.weatherIcon.image = (image: UIImage(named: "wind")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + default: + self.weatherIcon.image = (image: UIImage(named: "sun")) + self.weatherIcon.image = self.weatherIcon.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + self.weatherIcon.tintColor = UIColor.whiteColor() + } + } + + func loadForecast(obj: WeatherRawData){ + + if !allWeatherData.isEmpty + { + allWeatherData = [] + } + let days: Int + days = 7 + + for index in 1...days { + + let obj = WeatherList(day: obj.dailyWeather.data[index].date, + maxTemp: String(format: "%.1f", obj.dailyWeather.data[index].maxTemp), + minTemp: String(format: "%.1f", obj.dailyWeather.data[index].minTemp), + sunrise: obj.dailyWeather.data[index].sunrise, + sunset: obj.dailyWeather.data[index].sunset, + image: obj.dailyWeather.data[index].icon) + allWeatherData.append(obj!) + + } + } +} \ No newline at end of file diff --git a/Podfile b/Podfile index 9f9e096..7ddfd75 100644 --- a/Podfile +++ b/Podfile @@ -6,4 +6,4 @@ pod 'Freddy' pod 'AlamofireImage' pod 'AwesomeCache' -target 'APIClient' +target 'WeatherClient' From 5845602a84fe1e1ec354632784ba0344e55756df Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 10 Jun 2016 18:52:42 +0200 Subject: [PATCH 2/2] WeatherClient --- APIClient/Base.lproj/Main.storyboard | 5 +- APIClient/WeatherListViewController.swift | 7 +++ APIClient/WeatherViewController.swift | 75 +++++++++++++++-------- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/APIClient/Base.lproj/Main.storyboard b/APIClient/Base.lproj/Main.storyboard index 81dcfec..09e2be2 100644 --- a/APIClient/Base.lproj/Main.storyboard +++ b/APIClient/Base.lproj/Main.storyboard @@ -81,7 +81,7 @@ -