diff --git a/APIClient.xcodeproj/project.pbxproj b/APIClient.xcodeproj/project.pbxproj index a549a3b..16d0b2e 100644 --- a/APIClient.xcodeproj/project.pbxproj +++ b/APIClient.xcodeproj/project.pbxproj @@ -8,6 +8,10 @@ /* Begin PBXBuildFile section */ 078B558C6C77F3C6DCDC4678 /* Pods_APIClientUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82531BA6D6228998A00AB5B6 /* Pods_APIClientUITests.framework */; }; + 830DA5871CF437F100203B41 /* StarWarsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 830DA5861CF437F100203B41 /* StarWarsViewController.swift */; }; + 830DA5891CF57DEE00203B41 /* SWAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 830DA5881CF57DEE00203B41 /* SWAPI.swift */; }; + 83229B671CFC842800FF94B7 /* Structs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83229B661CFC842800FF94B7 /* Structs.swift */; }; + 835E5DB91D0440A300FD7CC3 /* MyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835E5DB81D0440A300FD7CC3 /* MyAPITests.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 */; }; @@ -39,6 +43,10 @@ 4FFA0A7AA37697BD5CBC3211 /* Pods_APIClientTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_APIClientTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 65C820A0F52E3181871F5ECA /* Pods-APIClientTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIClientTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-APIClientTests/Pods-APIClientTests.release.xcconfig"; sourceTree = ""; }; 82531BA6D6228998A00AB5B6 /* Pods_APIClientUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_APIClientUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 830DA5861CF437F100203B41 /* StarWarsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StarWarsViewController.swift; sourceTree = ""; }; + 830DA5881CF57DEE00203B41 /* SWAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SWAPI.swift; sourceTree = ""; }; + 83229B661CFC842800FF94B7 /* Structs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Structs.swift; sourceTree = ""; }; + 835E5DB81D0440A300FD7CC3 /* MyAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyAPITests.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; }; 874D06581CEF295E009A494D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -88,6 +96,7 @@ 872A27571CF0D4E200A988C4 /* View Controller */ = { isa = PBXGroup; children = ( + 830DA5861CF437F100203B41 /* StarWarsViewController.swift */, ); name = "View Controller"; sourceTree = ""; @@ -103,6 +112,8 @@ isa = PBXGroup; children = ( 872A275B1CF0D87100A988C4 /* APIResource.swift */, + 830DA5881CF57DEE00203B41 /* SWAPI.swift */, + 83229B661CFC842800FF94B7 /* Structs.swift */, ); name = Model; sourceTree = ""; @@ -156,6 +167,7 @@ isa = PBXGroup; children = ( 87EC71531CFA380F00FBDDDE /* Info.plist */, + 835E5DB81D0440A300FD7CC3 /* MyAPITests.swift */, ); path = APIClientTests; sourceTree = ""; @@ -468,7 +480,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 830DA5871CF437F100203B41 /* StarWarsViewController.swift in Sources */, 872A275C1CF0D87100A988C4 /* APIResource.swift in Sources */, + 83229B671CFC842800FF94B7 /* Structs.swift in Sources */, + 830DA5891CF57DEE00203B41 /* SWAPI.swift in Sources */, 874D06591CEF295E009A494D /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -477,6 +492,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 835E5DB91D0440A300FD7CC3 /* MyAPITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -636,10 +652,12 @@ baseConfigurationReference = F8B9811B1068B05E73195990 /* Pods-APIClientTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = APIClientTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "de.uni-heidelberg.ios-dev-kurs.APIClientTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/APIClient.app/APIClient"; }; name = Debug; @@ -649,6 +667,7 @@ baseConfigurationReference = 65C820A0F52E3181871F5ECA /* Pods-APIClientTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = APIClientTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "de.uni-heidelberg.ios-dev-kurs.APIClientTests"; diff --git a/APIClient/.xcdatamodeld/Datatest.xcdatamodel/contents b/APIClient/.xcdatamodeld/Datatest.xcdatamodel/contents new file mode 100644 index 0000000..ff64d29 --- /dev/null +++ b/APIClient/.xcdatamodeld/Datatest.xcdatamodel/contents @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/APIClient/AppDelegate.swift b/APIClient/AppDelegate.swift index 630c3ed..dae3899 100644 --- a/APIClient/AppDelegate.swift +++ b/APIClient/AppDelegate.swift @@ -7,14 +7,22 @@ // import UIKit +import Moya @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? + let starWAPI = MoyaProvider() func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + + if let starWarsViewController = (window?.rootViewController as? UINavigationController)?.topViewController as? StarWarsViewController { +// API to ViewController + starWarsViewController.starWAPI = starWAPI + } + return true } diff --git a/APIClient/Base.lproj/Main.storyboard b/APIClient/Base.lproj/Main.storyboard index 69b2fbf..1eb6f98 100644 --- a/APIClient/Base.lproj/Main.storyboard +++ b/APIClient/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -21,24 +21,149 @@ - + - + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + - + diff --git a/APIClient/Info.plist b/APIClient/Info.plist index 40c6215..8c7d69f 100644 --- a/APIClient/Info.plist +++ b/APIClient/Info.plist @@ -22,6 +22,17 @@ 1 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSExceptionDomains + + swapi.co + + NSExceptionAllowsInsecureHTTPLoads + + + + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/APIClient/SWAPI.swift b/APIClient/SWAPI.swift new file mode 100644 index 0000000..c4315fb --- /dev/null +++ b/APIClient/SWAPI.swift @@ -0,0 +1,90 @@ +// +// SWAPI.swift +// APIClient +// +// Created by Christoph Blattgerste on 25.05.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation +import Moya +import Freddy + + +//adress of the used API: ("http://swapi.co/api/") + +enum SWAPI: Moya.TargetType, Cacheable { + + case starships (NamedResource) + case planets (NamedResource) + case species (NamedResource) + + var baseURL: NSURL {return NSURL(string: "http://swapi.co/api")! } + + var path : String { + switch self { + case .starships(let namedResource): return "/starships/\(namedResource.name)" + case .planets(let namedResource): return "/planets/\(namedResource.name)" + case .species(let namedResource): return "/species/\(namedResource.name)" + } + } + + var method: Moya.Method {return .GET} + + var parameters: [String : AnyObject]? { + switch self { + default: return nil + } + } + + var sampleData: NSData { + switch self { +// case .starships(let namedResource): +// return +// "name": "CR90 corvette", +// "model": "CR90 corvette", +// "manufacturer": "Corellian Engineering Corporation", +// "cost_in_credits": "3500000", +// "length": "150", +// "max_atmosphering_speed": "950", +// "crew": "165", +// "passengers": "600", +// "cargo_capacity": "3000000", +// "consumables": "1 year", +// "hyperdrive_rating": "2.0", +// "MGLT": "60", +// "starship_class": "corvette", +// "pilots": [], +// "films": [ +// "http://swapi.co/api/films/6/", +// "http://swapi.co/api/films/3/", +// "http://swapi.co/api/films/1/" +// ], +// "created": "2014-12-10T14:20:33.369000Z", +// "edited": "2014-12-22T17:35:45.408368Z", +// "url": "http://swapi.co/api/starships/2/" +// .dataUsingEncoding(NSUTF8StringEncoding)! + default: + return "".dataUsingEncoding(NSUTF8StringEncoding)! + } + } + + var cacheIdentifier: String { + return self.path + } +} + + +struct NamedResource: Freddy.JSONDecodable { + + let name: String + + init(name: String) { + self.name = name + } + + init(json: JSON) throws { + self.name = try json.string("name") + } + +} \ No newline at end of file diff --git a/APIClient/StarWarsViewController.swift b/APIClient/StarWarsViewController.swift new file mode 100644 index 0000000..2642bbb --- /dev/null +++ b/APIClient/StarWarsViewController.swift @@ -0,0 +1,180 @@ +// +// StarWarsViewController.swift +// APIClient +// +// Created by Christoph Blattgerste on 24.05.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import UIKit +import Freddy +import Moya +import AlamofireImage + +class StarWarsViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate { + + override func viewDidLoad() { + super.viewDidLoad() + self.sWPickerView.dataSource = self + self.sWPickerView.delegate = self + self.entrieDataSS = nil + self.entrieDataSS = nil + self.entrieDataSp = nil + pickerLabel.text = "Select a \(selectedEndpoint):" + numberSelection.delegate = self + } + + var starWAPI : MoyaProvider! + + var entrieDataSS: Starships? { + didSet { + outputOne.text = entrieDataSS?.starshipClass + outputTwo.text = entrieDataSS?.costInCredits + outputZero.text = entrieDataSS?.name + labelOne.text = "Its class:" + labelTwo.text = "Its costs[credits]:" + labelZero.text = "Starships name:" + } + } + var entrieDataPl: Planets? { + didSet { + outputOne.text = entrieDataPl?.terrain + outputTwo.text = entrieDataPl?.population + outputZero.text = entrieDataPl?.name + labelOne.text = "Its terrain:" + labelTwo.text = "Its population:" + labelZero.text = "Planets name:" + + } + } + var entrieDataSp: Species? { + didSet { + outputZero.text = entrieDataSp?.name + outputOne.text = entrieDataSp?.homeworld + outputTwo.text = entrieDataSp?.language + labelZero.text = "Species name:" + labelOne.text = "Its homeworld:" + labelTwo.text = "Its language:" + } + } + + + @IBOutlet weak var sWPickerView: UIPickerView! + @IBOutlet weak var pickerLabel: UILabel! + @IBOutlet weak var labelOne: UILabel! + @IBOutlet weak var labelTwo: UILabel! + @IBOutlet weak var labelZero: UILabel! + @IBOutlet weak var outputOne: UILabel! + @IBOutlet weak var outputTwo: UILabel! + @IBOutlet weak var outputZero: UILabel! + @IBOutlet weak var numberSelection: UITextField! + @IBOutlet weak var loadingIndicator: UIActivityIndicatorView! + + @IBAction func actNumberSelection(sender: AnyObject) { + sender.resignFirstResponder() + switch selectedEndpoint { + case "Starship": + loadStarship(NamedResource(name: numberSelection.text ?? "")) + case "Planet": + loadPlanet(NamedResource(name: numberSelection.text ?? "")) + case "Species": + loadSpecies(NamedResource(name: numberSelection.text ?? "")) + default: + break + } + } + + let pickerData = ["Starship","Planet","Species"] + + private var selectedEndpoint = "Starship" + + + + +// Functions to initialize UIPickerView + func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { + return 1 + } + func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return pickerData.count + } + func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + return pickerData[row] + } + func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { +// pickerLabel.text = "Select a \(pickerData[row]):" + selectedEndpoint = pickerData[row] + pickerLabel.text = "Select a \(selectedEndpoint):" + } + +// load selected Endpoint from API URL +// depending on PickerWheel selection + func loadStarship(starship: NamedResource) { + loadingIndicator.startAnimating() + starWAPI.request(.starships(starship)) { result in + self.loadingIndicator.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 star_ship = try Starships(json: json) + // Configure view according to model + self.entrieDataSS = star_ship + } catch { + print(error) + } + case .Failure(let error): + print(error) + } + } + } + func loadPlanet(planet: NamedResource) { + loadingIndicator.startAnimating() + starWAPI.request(.planets(planet)) { result in + self.loadingIndicator.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 pla_net = try Planets(json: json) + // Configure view according to model + self.entrieDataPl = pla_net + } catch { + print(error) + } + case .Failure(let error): + print(error) + } + } + } + + func loadSpecies(specie: NamedResource) { + loadingIndicator.startAnimating() + starWAPI.request(.species(specie)) { result in + self.loadingIndicator.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 spe_cies = try Species(json: json) + // Configure view according to model + self.entrieDataSp = spe_cies + } catch { + print(error) + } + case .Failure(let error): + print(error) + } + } + } + +} diff --git a/APIClient/Structs.swift b/APIClient/Structs.swift new file mode 100644 index 0000000..8af2d22 --- /dev/null +++ b/APIClient/Structs.swift @@ -0,0 +1,53 @@ +// +// Structs.swift +// APIClient +// +// Created by Christoph Blattgerste on 30.05.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation +import Freddy +import UIKit + +struct Starships: JSONDecodable { + + let name : String + + let starshipClass : String + + let costInCredits : String + + init (json: JSON) throws { + self.name = try json.string("name") + self.costInCredits = try json.string("cost_in_credits") + self.starshipClass = try json.string("starship_class") + } +} + +struct Planets: JSONDecodable { + + let name : String + let population : String + let terrain : String + + init(json: JSON) throws { + self.name = try json.string("name") + self.population = try json.string("population") + self.terrain = try json.string("terrain") + } +} + +struct Species: JSONDecodable { + + let name : String + let homeworld : String + let language : String + + init(json: JSON) throws { + self.name = try json.string("name") + self.language = try json.string("language") + self.homeworld = try json.string("homeworld") + } + +} diff --git a/APIClientTests/MyAPITests.swift b/APIClientTests/MyAPITests.swift new file mode 100644 index 0000000..f531e69 --- /dev/null +++ b/APIClientTests/MyAPITests.swift @@ -0,0 +1,32 @@ +// +// MyAPITests.swift +// APIClient +// +// Created by Christoph Blattgerste on 05.06.16. +// Copyright © 2016 iOS Dev Kurs Universität Heidelberg. All rights reserved. +// + +import Foundation + +import XCTest + +@testable import APIClient + +import Nimblek0 + +class MyAPITests : XCTestCase { + override func setUp() { + super.setUp() + } + override func tearDown() { + super.tearDown() + } +//eigene Test Funktionen + func testFirstTry() { + expect(1+1) == 2 + expect( + } + +} + + diff --git a/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + +