├── Cartfile
├── Cartfile.resolved
├── .gitignore
├── ReswiftAppCoordinatorDemo
├── fonts.swift
├── colors.swift
├── LoadingActions.swift
├── ErrorMessageActions.swift
├── StringUtil.swift
├── SearchResultsCoordinator.swift
├── AppState.swift
├── AppCoordinator.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── PropertyDetailSceneViewController.swift
├── SearchView.swift
├── SearchResultViewController.swift
├── PropertyDetailView.swift
├── SearchSceneCoordinator.swift
├── SearchResultView.swift
├── Info.plist
├── SearchSceneViewController.swift
├── PropertyApi.swift
├── LocationTracker.swift
├── BaseViewController.swift
├── XibBaseView.swift
├── SearchResultView.xib
├── AppDelegate.swift
├── PropertyActions.swift
├── AppReducer.swift
├── Base.lproj
│ └── LaunchScreen.storyboard
├── SearchView.xib
└── PropertyDetailView.xib
├── ReswiftAppCoordinatorDemo.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── xnliu.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── ReswiftAppCoordinatorDemo.xcscheme
└── project.pbxproj
└── ReswiftAppCoordinatorDemoTests
├── StringUtilSpec.swift
└── Info.plist
/Cartfile:
--------------------------------------------------------------------------------
1 | github "ReSwift/ReSwift"
2 | github "Alamofire/Alamofire" ~> 4.0
3 | github "Quick/Quick"
4 | github "Quick/Nimble"
5 |
6 |
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "Alamofire/Alamofire" "4.4.0"
2 | github "Quick/Nimble" "v7.0.0"
3 | github "Quick/Quick" "v1.1.0"
4 | github "ReSwift/ReSwift" "4.0.0"
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Mac OS X
2 | *.DS_Store
3 |
4 | # Xcode
5 | *.pbxuser
6 | *.mode1v3
7 | *.mode2v3
8 | *.perspectivev3
9 | *.xcuserstate
10 | project.xcworkspace/
11 | xcuserdata/
12 |
13 | #Carthage
14 | Carthage/
15 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/fonts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // fonts.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/colors.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Colors.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | struct Colors {
10 | static let blue = "#656565"
11 | }
12 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/LoadingActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoadingActions.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import ReSwift
9 |
10 | struct StartLoading: Action {}
11 | struct EndLoading: Action {}
12 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/ErrorMessageActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ErrorMessageReducer.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import ReSwift
10 |
11 | struct SaveErrorMessage: Action {
12 | let errorMessage:String
13 | }
14 |
15 | struct CleanErrorMessage: Action {}
16 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemoTests/StringUtilSpec.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StringUtilTests.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 09/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import Quick
9 | import Nimble
10 |
11 | class StringUtilSpec: QuickSpec {
12 | override func spec() {
13 | describe("formatForPound") {
14 | it("format double to string in pound format") {
15 | expect(StringUtil.formatForPound(59500.0)).to(equal("£59,500"))
16 | }
17 | }
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/StringUtil.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StringUtility.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 09/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import Foundation
9 |
10 | struct StringUtil {
11 | static func formatForPound(_ number: Double) -> String{
12 | let numberFormatter = NumberFormatter()
13 | numberFormatter.numberStyle = NumberFormatter.Style.decimal
14 | let numberString = numberFormatter.string(from: NSNumber(value: number))!
15 | return "£\(numberString)"
16 | }}
17 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo.xcodeproj/xcuserdata/xnliu.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ReswiftAppCoordinatorDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | DF3072681E1BA625005AA130
16 |
17 | primary
18 |
19 |
20 | DF30727C1E1BA625005AA130
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchResultsCoordinator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultsCoordinator.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 09/03/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | protocol SearchResultsSceneCoordinatorProtocol {
12 | func showPropertyDetail(index:Int)
13 | }
14 |
15 | class SearchResultsSceneCoordinator:AppCoordinator,SearchResultsSceneCoordinatorProtocol {
16 | let propertyActionCreater = PropertyActionCreater()
17 |
18 | func showPropertyDetail(index:Int) {
19 | mainStore.dispatch(UpdateSelectedProperty(selectedPropertyIndex: index))
20 | let propertyDetailVC = PropertyDetailSceneViewController();
21 | self.rootVC.pushViewController(propertyDetailVC, animated: true)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/AppState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppState.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import ReSwift
9 |
10 | struct AppState: StateType {
11 | var isLoading:Bool = false
12 | var errorMessage:String?
13 | var property:PropertyState
14 | }
15 |
16 | struct PropertyState {
17 | var searchCriteria:SearchCriteria?
18 | var properties:[PropertyDetail]?
19 | var selectedProperty:Int = -1
20 | }
21 |
22 | struct SearchCriteria {
23 | let placeName:String?
24 | let centerPoint:String?
25 | }
26 |
27 | struct PropertyDetail {
28 | var title:String
29 | var price:Double
30 | var imgUrl:String
31 | var bedroomNumber:Int = -1
32 | var propertyType:String
33 | var bathroomNumber:Int = -1
34 | var description:String
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/AppCoordinator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppCoordinator.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 03/01/2017.
6 | //
7 |
8 | import Foundation
9 | import UIKit
10 |
11 | class AppCoordinator {
12 | var rootVC: UINavigationController
13 |
14 | init(_ rootVC: UINavigationController){
15 | self.rootVC = rootVC
16 | }
17 |
18 | func start() {
19 | let searchVC = SearchSceneViewController();
20 | let searchSceneCoordinator = SearchSceneCoordinator(self.rootVC)
21 | searchVC.searchSceneCoordinator = searchSceneCoordinator
22 | self.rootVC.pushViewController(searchVC, animated: true)
23 | }
24 |
25 | func showAlert(errorMessage:String) {
26 | let alert = UIAlertController(title: "Oops!", message:errorMessage, preferredStyle: .alert)
27 | alert.addAction(UIAlertAction(title: "OK", style: .default))
28 | self.rootVC.topViewController?.present(alert, animated: true)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/PropertyDetailSceneViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PropertyDetailSceneViewController.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 09/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | class PropertyDetailSceneViewController: BaseViewController {
10 | var propertyDetailView:PropertyDetailView?
11 |
12 |
13 | //MARK: update state
14 | override func newState(state: AppState) {
15 | if let property = state.property.properties?[state.property.selectedProperty] {
16 | print("start updating...")
17 | self.propertyDetailView?.update(property: property)
18 | }
19 |
20 | super.newState(state: state)
21 | }
22 |
23 | //MARK: lifecycle
24 | override func viewDidLoad() {
25 | super.viewDidLoad()
26 | propertyDetailView = PropertyDetailView(frame: self.view.bounds)
27 | self.view.addSubview(propertyDetailView!)
28 | }
29 |
30 | override func didReceiveMemoryWarning() {
31 | super.didReceiveMemoryWarning()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchView.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 06/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SearchView:XibBaseView {
12 |
13 | @IBOutlet var placeNameField:UITextField!
14 |
15 | var goButtonOnClick:((_ searchCriteria:SearchCriteria) -> Void)?
16 | var locationButtonOnClick: (() -> Void)?
17 |
18 | @IBAction func goButtonTapped() {
19 | if self.placeNameField.text == "" {
20 | self.placeNameField.text = self.placeNameField.placeholder
21 | }
22 |
23 | let searchCriteria = SearchCriteria(
24 | placeName: self.placeNameField.text,
25 | centerPoint:nil
26 | )
27 |
28 | if let goButtonCallback = self.goButtonOnClick{
29 | goButtonCallback(searchCriteria)
30 | }
31 | }
32 |
33 | @IBAction func locationButtonTapped() {
34 |
35 | if let locationButtonCallback = self.locationButtonOnClick {
36 | locationButtonCallback()
37 | }
38 | }
39 |
40 | func update(searchCriteria:SearchCriteria) {
41 | self.placeNameField.text = searchCriteria.placeName
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchResultViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultViewController.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 08/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SearchResultSceneViewController: BaseViewController {
12 |
13 | var searchResultCoordinator: SearchResultsSceneCoordinatorProtocol?
14 | var searchResultView:SearchResultView?
15 |
16 | //MARK: update state
17 | override func newState(state: AppState) {
18 | if let properties = state.property.properties{
19 | self.searchResultView?.update(properties: properties)
20 | }
21 | super.newState(state: state)
22 | }
23 |
24 | //MARK: user action
25 | func showPropertyDetail(index:Int) {
26 | self.searchResultCoordinator?.showPropertyDetail(index: index)
27 | }
28 |
29 | //MARK: lifecycle
30 | override func viewDidLoad() {
31 | super.viewDidLoad()
32 | searchResultView = SearchResultView(frame: self.view.bounds)
33 | searchResultView?.selectPropertyAt = self.showPropertyDetail
34 | self.view.addSubview(searchResultView!)
35 | }
36 |
37 | override func didReceiveMemoryWarning() {
38 | super.didReceiveMemoryWarning()
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/PropertyDetailView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PropertyDetailView.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 09/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import UIKit
9 |
10 | class PropertyDetailView:XibBaseView{
11 |
12 | @IBOutlet var imageView:UIImageView?
13 | @IBOutlet var nameLabel:UILabel?
14 | @IBOutlet var priceLabel:UILabel?
15 | @IBOutlet var highlightLabel:UILabel?
16 | @IBOutlet var descriptionLabel:UILabel?
17 |
18 | func update(property:PropertyDetail) {
19 | if let url = URL(string: property.imgUrl), let data = NSData(contentsOf: url)
20 | {
21 | self.imageView?.image = UIImage(data: data as Data)
22 | }
23 | self.nameLabel?.text = property.title
24 | self.priceLabel?.text = StringUtil.formatForPound(property.price)
25 | self.highlightLabel?.text = self.combine(property: property)
26 | self.highlightLabel?.sizeToFit()
27 | self.descriptionLabel?.text = property.description
28 | self.descriptionLabel?.sizeToFit()
29 | }
30 |
31 | private func combine(property:PropertyDetail) -> String {
32 | var result = "\(property.bedroomNumber) bed \(property.propertyType)"
33 |
34 | if(property.bathroomNumber != -1) {
35 | result += "," + String(property.bathroomNumber) + " "
36 | result += property.bathroomNumber > 1 ? "bathrooms" : "bathroom"
37 | }
38 | return result
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchSceneCoordinator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchSceneCoordinator.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 09/03/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | protocol SearchSceneCoordinatorProtocol {
12 | func searchByCity(searchCriteria:SearchCriteria)
13 | func searchByCurrentLocation()
14 | }
15 |
16 | class SearchSceneCoordinator: AppCoordinator, SearchSceneCoordinatorProtocol {
17 | let propertyActionCreater = PropertyActionCreater()
18 |
19 | func searchByCity(searchCriteria:SearchCriteria) {
20 | mainStore.dispatch(SaveErrorMessage(errorMessage: ""))
21 | mainStore.dispatch(
22 | propertyActionCreater.searchProperties(searchCriteria: searchCriteria){
23 | self.pushSearchResultViewController()
24 | }
25 | )
26 | }
27 |
28 | func searchByCurrentLocation() {
29 | mainStore.dispatch(SaveErrorMessage(errorMessage: ""))
30 | mainStore.dispatch(propertyActionCreater.searchPropertiesByCurrentLocation(){
31 | self.pushSearchResultViewController()
32 | })
33 | }
34 |
35 | private func pushSearchResultViewController() {
36 | let searchResultVC = SearchResultSceneViewController();
37 | let searchResultCoordinator = SearchResultsSceneCoordinator(self.rootVC)
38 | searchResultVC.searchResultCoordinator = searchResultCoordinator
39 | self.rootVC.pushViewController(searchResultVC, animated: true)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchResultView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultView.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 08/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import UIKit
9 |
10 | class SearchResultView:XibBaseView{
11 |
12 | @IBOutlet var resultTableView:UITableView?
13 | var properties:[PropertyDetail]?
14 | var selectPropertyAt:((_ index:Int) -> Void)?
15 |
16 | func update(properties:[PropertyDetail]) {
17 | self.properties = properties
18 | }
19 | }
20 |
21 | extension SearchResultView: UITableViewDelegate, UITableViewDataSource {
22 |
23 | func numberOfSections(in tableView: UITableView) -> Int {
24 | return 1
25 | }
26 |
27 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
28 | return self.properties?.count ?? 0
29 | }
30 |
31 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
32 | var cell = tableView.dequeueReusableCell(withIdentifier: "property")
33 |
34 | if cell == nil {
35 | cell = UITableViewCell(style: .subtitle, reuseIdentifier: "property")
36 | }
37 |
38 | if let property = self.properties?[indexPath.row] {
39 | cell?.textLabel?.text = property.title
40 | cell?.detailTextLabel?.text = StringUtil.formatForPound(property.price)
41 | }
42 |
43 | return cell!
44 | }
45 |
46 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
47 | self.selectPropertyAt?(indexPath.row)
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSLocationWhenInUseUsageDescription
6 | track current location for better service
7 | NSLocationAlwaysUsageDescription
8 | track current location for better service
9 | NSAppTransportSecurity
10 |
11 | NSAllowsArbitraryLoads
12 |
13 |
14 | CFBundleDevelopmentRegion
15 | en
16 | CFBundleDisplayName
17 | ReApp
18 | CFBundleExecutable
19 | $(EXECUTABLE_NAME)
20 | CFBundleIdentifier
21 | $(PRODUCT_BUNDLE_IDENTIFIER)
22 | CFBundleInfoDictionaryVersion
23 | 6.0
24 | CFBundleName
25 | $(PRODUCT_NAME)
26 | CFBundlePackageType
27 | APPL
28 | CFBundleShortVersionString
29 | 1.0
30 | CFBundleVersion
31 | 1
32 | LSRequiresIPhoneOS
33 |
34 | UILaunchStoryboardName
35 | LaunchScreen
36 | UIRequiredDeviceCapabilities
37 |
38 | armv7
39 |
40 | UISupportedInterfaceOrientations
41 |
42 | UIInterfaceOrientationPortrait
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchSceneViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 03/01/2017.
6 | //
7 |
8 | import UIKit
9 | import ReSwift
10 |
11 | class SearchSceneViewController: BaseViewController {
12 |
13 | var searchSceneCoordinator:SearchSceneCoordinatorProtocol?
14 | var searchView:SearchView?
15 |
16 | //MARK: update state
17 | override func newState(state: AppState) {
18 | self.update(state: state)
19 | super.newState(state: state)
20 | }
21 |
22 | private func update(state: AppState) {
23 | if let searchCriteria = state.property.searchCriteria {
24 | searchView?.update(searchCriteria: searchCriteria)
25 | }
26 | if let errorMessage = state.errorMessage, !errorMessage.isEmpty {
27 | self.showAlert(errorMessage: errorMessage)
28 | }
29 | }
30 |
31 | //MARK: user action
32 | func searchByCity(searchCriteria:SearchCriteria) {
33 | searchSceneCoordinator?.searchByCity(searchCriteria: searchCriteria)
34 | }
35 |
36 | func searchByCurrentLocation() {
37 | searchSceneCoordinator?.searchByCurrentLocation()
38 | }
39 |
40 | //MARK: lifecycle
41 | override func viewDidLoad() {
42 | super.viewDidLoad()
43 | searchView = SearchView(frame: self.view.bounds)
44 | searchView?.goButtonOnClick = self.searchByCity
45 | searchView?.locationButtonOnClick = self.searchByCurrentLocation
46 | self.view.addSubview(searchView!)
47 | }
48 |
49 | override func didReceiveMemoryWarning() {
50 | super.didReceiveMemoryWarning()
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/PropertyApi.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PropertyApi.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import Alamofire
9 |
10 | struct PropertyApi {
11 | func findProperties(searchCriteria:SearchCriteria, success: @escaping (_ response: Any) -> Void, failure: @escaping (_ error: Error?) -> Void ) {
12 |
13 | let parameters = parametersForQuery(searchCriteria: searchCriteria)
14 |
15 | Alamofire.request("http://api.nestoria.co.uk/api", parameters:parameters).responseJSON(
16 | completionHandler: { response in
17 | switch response.result {
18 | case .success(let JSON):
19 | print("Validation Successful")
20 | print(response.data ?? "Data is empty")
21 | success(JSON)
22 | case .failure(let error):
23 | print(error)
24 | failure(error)
25 | }
26 | })
27 | }
28 |
29 | private func parametersForQuery(searchCriteria:SearchCriteria) -> [String : Any]{
30 | var queryParameters = [
31 | "country": "uk",
32 | "pretty": "1",
33 | "encoding": "json",
34 | "listing_type": "buy",
35 | "action": "search_listings",
36 | "page": 1
37 | ] as [String : Any]
38 | if (searchCriteria.placeName != nil) {
39 | queryParameters["place_name"] = searchCriteria.placeName
40 | }
41 | if(searchCriteria.centerPoint != nil) {
42 | queryParameters["centre_point"] = searchCriteria.centerPoint
43 | }
44 |
45 | return queryParameters
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/LocationTracker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LocationTracker.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 06/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import CoreLocation
10 |
11 | class LocationTracker :NSObject, CLLocationManagerDelegate {
12 | var locationManager:CLLocationManager?
13 | var onSuccess: ((String) -> Void)?
14 | var onFailure: ((String) -> Void)?
15 |
16 | func getCurrentLocation(success: ((String) -> Void)?, fail: ((String) -> Void)?){
17 | self.locationManager = CLLocationManager()
18 | self.onSuccess = success
19 | self.onFailure = fail
20 |
21 | // Ask for Authorisation from the User.
22 | self.locationManager?.requestAlwaysAuthorization()
23 |
24 | // For use in foreground
25 | self.locationManager?.requestWhenInUseAuthorization()
26 |
27 | if CLLocationManager.locationServicesEnabled() {
28 | locationManager?.delegate = self
29 | locationManager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
30 | locationManager?.startUpdatingLocation()
31 | }
32 | }
33 |
34 | func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
35 | let locValue:CLLocationCoordinate2D = manager.location!.coordinate
36 | self.onSuccess?("\(locValue.latitude),\(locValue.longitude)")
37 | self.locationManager?.stopUpdatingLocation()
38 | self.locationManager = nil
39 | }
40 |
41 | func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
42 | self.onFailure?(error.localizedDescription)
43 | self.locationManager?.stopUpdatingLocation()
44 | self.locationManager = nil
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/BaseViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseViewController.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 06/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ReSwift
11 |
12 | class BaseViewController: UIViewController, StoreSubscriber {
13 | typealias StoreSubscriberStateType = AppState
14 | let activityInd = UIActivityIndicatorView(activityIndicatorStyle:.gray)
15 | var appCoordinator:AppCoordinator?
16 |
17 | //MARK: update state
18 | func newState(state: AppState) {
19 | if state.isLoading {
20 | self.view.addSubview(self.activityInd)
21 | self.activityInd.startAnimating()
22 | } else {
23 | self.activityInd.stopAnimating()
24 | }
25 | }
26 |
27 | func showAlert(errorMessage:String) {
28 | let alert = UIAlertController(title: "Oops!", message:errorMessage, preferredStyle: .alert)
29 | alert.addAction(UIAlertAction(title: "OK", style: .default))
30 | self.navigationController?.topViewController?.present(alert, animated: true)
31 | }
32 |
33 | //MARK: lifecycle
34 | override func viewWillAppear(_ animated: Bool) {
35 | super.viewWillAppear(animated)
36 | mainStore.subscribe(self) { state in state }
37 | }
38 |
39 | override func viewWillDisappear(_ animated: Bool) {
40 | super.viewWillDisappear(animated)
41 | mainStore.unsubscribe(self)
42 | }
43 |
44 | override func viewDidLoad() {
45 | super.viewDidLoad()
46 | configActivityIndicator()
47 | }
48 |
49 | func configActivityIndicator() {
50 | self.activityInd.frame = CGRect(x:0.0, y:0.0, width:40.0, height:40.0);
51 | self.activityInd.hidesWhenStopped = true
52 | self.activityInd.center = self.view.center
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/XibBaseView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchView.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import UIKit
9 |
10 | class XibBaseView:UIView {
11 |
12 | var nibView: UIView?
13 |
14 | override init(frame: CGRect) {
15 | super.init(frame: frame)
16 |
17 | initialize()
18 | }
19 |
20 | required init?(coder aDecoder: NSCoder) {
21 | super.init(coder: aDecoder)
22 |
23 | initialize()
24 | }
25 |
26 | func initialize() {
27 | if let nibName = self.nibName {
28 | nibView = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?[0] as? UIView
29 |
30 | if let actualNibView = nibView {
31 | actualNibView.frame = self.bounds
32 | super.addSubview(actualNibView)
33 | actualNibView.translatesAutoresizingMaskIntoConstraints = false
34 | self.addConstraint(format: "H:|[view]|", views: ["view": actualNibView])
35 | self.addConstraint(format: "V:|[view]|", views: ["view": actualNibView])
36 | }
37 | }
38 | }
39 | func addConstraint(format: String, views: [String : UIView]) {
40 | let constraints = NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: views)
41 | self.addConstraints(constraints)
42 | }
43 |
44 | override func addSubview(_ view: UIView) {
45 | if let actualNibView = nibView {
46 | actualNibView.addSubview(view)
47 | } else {
48 | super.addSubview(view)
49 | }
50 | }
51 |
52 | var nibName: String? {
53 | let typeLongName = type(of: self).description()
54 | let tokens = typeLongName.characters.split {$0 == "."}.map(String.init)
55 | return tokens.last!
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchResultView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 03/01/2017.
6 | //
7 |
8 | import UIKit
9 | import ReSwift
10 |
11 | let mainStore = Store(
12 | reducer: AppReducer,
13 | state: nil
14 | )
15 |
16 | @UIApplicationMain
17 | class AppDelegate: UIResponder, UIApplicationDelegate {
18 |
19 | var window: UIWindow?
20 | var appCoordinator: AppCoordinator!
21 |
22 |
23 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
24 | window = UIWindow()
25 | let rootVC = UINavigationController()
26 | window?.rootViewController = rootVC
27 | appCoordinator = AppCoordinator(rootVC)
28 | appCoordinator.start()
29 | window?.makeKeyAndVisible()
30 | return true
31 | }
32 |
33 | func applicationWillResignActive(_ application: UIApplication) {
34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
35 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
36 | }
37 |
38 | func applicationDidEnterBackground(_ application: UIApplication) {
39 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
41 | }
42 |
43 | func applicationWillEnterForeground(_ application: UIApplication) {
44 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
45 | }
46 |
47 | func applicationDidBecomeActive(_ application: UIApplication) {
48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
49 | }
50 |
51 | func applicationWillTerminate(_ application: UIApplication) {
52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
53 | }
54 |
55 |
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/PropertyActions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PropertyActions.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 |
9 | import ReSwift
10 |
11 | struct UpdateSearchCriteria: Action {
12 | let searchCriteria:SearchCriteria
13 | }
14 |
15 | struct UpdateProperties: Action {
16 | let response:Any
17 | }
18 |
19 | struct UpdateSelectedProperty: Action {
20 | let selectedPropertyIndex:Int
21 | }
22 |
23 | struct PropertyActionCreater {
24 | typealias ActionCreator = (_ state: AppState, _ store: Store) -> Action?
25 | typealias AsyncActionCreator = (_ state: AppState, _ store: Store, _ callback: @escaping (_ actionCreator: ActionCreator) -> Void ) -> Void
26 | let propertyApi = PropertyApi()
27 | let locationTracker = LocationTracker()
28 |
29 | func searchProperties(searchCriteria: SearchCriteria, _ callback:(() -> Void)?) -> ActionCreator {
30 | return { state, store in
31 | store.dispatch(UpdateSearchCriteria(searchCriteria: searchCriteria))
32 |
33 | self.propertyApi.findProperties(
34 | searchCriteria: searchCriteria,
35 | success: { (response) in
36 | store.dispatch(UpdateProperties(response: response))
37 | store.dispatch(EndLoading())
38 | callback?()
39 | },
40 | failure: { (error) in
41 | store.dispatch(EndLoading())
42 | store.dispatch(SaveErrorMessage(errorMessage: (error?.localizedDescription)!))
43 | }
44 | )
45 | return StartLoading()
46 | }
47 | }
48 |
49 |
50 | func searchPropertiesByCurrentLocation(_ nextStep:(() -> Void)?) -> AsyncActionCreator {
51 |
52 | return { maybeState, store, callback in
53 | store.dispatch(StartLoading())
54 | self.locationTracker.getCurrentLocation(
55 | success: { currentLocation in
56 | let searchCriteria = SearchCriteria(
57 | placeName:nil,
58 | centerPoint: currentLocation
59 | )
60 | callback(self.searchProperties(searchCriteria: searchCriteria, nextStep))
61 | },
62 | fail: { errorMessage in
63 | store.dispatch(SaveErrorMessage(errorMessage: errorMessage))
64 | store.dispatch(EndLoading())
65 | }
66 | )
67 | }
68 | }
69 |
70 | }
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/AppReducer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppReducer.swift
3 | // ReswiftAppCoordinatorDemo
4 | //
5 | // Created by Xianning Liu on 04/01/2017.
6 | // Copyright © 2017 xianlinbox. All rights reserved.
7 | //
8 | import ReSwift
9 |
10 | func AppReducer(action: Action, state: AppState?) -> AppState {
11 | return AppState(
12 | isLoading:loadingReducer(state?.isLoading, action: action),
13 | errorMessage:errorMessageReducer(state?.errorMessage, action: action),
14 | property:propertyReducer(state?.property, action: action)
15 | )
16 | }
17 |
18 | func loadingReducer(_ state: Bool?, action: Action) -> Bool {
19 | var state = state ?? false
20 |
21 | switch action {
22 | case _ as StartLoading:
23 | state = true
24 | case _ as EndLoading:
25 | state = false
26 | default:
27 | break
28 | }
29 |
30 | return state
31 | }
32 |
33 | func errorMessageReducer(_ state: String?, action: Action) -> String {
34 | var state = state ?? ""
35 |
36 | switch action {
37 | case let action as SaveErrorMessage:
38 | state = action.errorMessage
39 | case _ as CleanErrorMessage:
40 | state = ""
41 | default:
42 | break
43 | }
44 |
45 | return state
46 | }
47 |
48 | func propertyReducer(_ state: PropertyState?, action: Action) -> PropertyState {
49 | var state = state ?? PropertyState()
50 |
51 | switch action {
52 | case let action as UpdateSearchCriteria:
53 | state.searchCriteria = action.searchCriteria
54 | case let action as UpdateProperties:
55 | let responseData = action.response as! NSDictionary
56 | let response = responseData.object(forKey: "response") as! NSDictionary
57 | let propertyList = response.object(forKey: "listings") as! NSArray
58 |
59 | state.properties = propertyList.map({ (property) -> PropertyDetail in
60 | let props = property as! NSDictionary
61 |
62 | return PropertyDetail(
63 | title:props.object(forKey: "title") as! String,
64 | price:props.object(forKey: "price") as! Double,
65 | imgUrl:props.object(forKey: "img_url") as! String,
66 | bedroomNumber: Int((props.object(forKey: "bedroom_number") as? Int64) ?? -1),
67 | propertyType: props.object(forKey: "property_type") as! String,
68 | bathroomNumber: Int((props.object(forKey: "bathroom_number") as? Int64) ?? -1),
69 | description:props.object(forKey: "summary") as! String
70 | )
71 | })
72 | case let action as UpdateSelectedProperty:
73 | state.selectedProperty = action.selectedPropertyIndex
74 | default:
75 | break
76 | }
77 |
78 | return state
79 | }
80 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo.xcodeproj/xcuserdata/xnliu.xcuserdatad/xcschemes/ReswiftAppCoordinatorDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/SearchView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
53 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo/PropertyDetailView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
40 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
62 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/ReswiftAppCoordinatorDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | DF0E3FB01E2369BA00D00586 /* PropertyDetailSceneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF0E3FAF1E2369BA00D00586 /* PropertyDetailSceneViewController.swift */; };
11 | DF0E3FB21E236C0400D00586 /* PropertyDetailView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DF0E3FB11E236C0400D00586 /* PropertyDetailView.xib */; };
12 | DF0E3FB41E236C1900D00586 /* PropertyDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF0E3FB31E236C1900D00586 /* PropertyDetailView.swift */; };
13 | DF0E3FB71E2378AF00D00586 /* StringUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF0E3FB61E2378AF00D00586 /* StringUtil.swift */; };
14 | DF0E3FBA1E237C9F00D00586 /* StringUtilSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF0E3FB91E237C9F00D00586 /* StringUtilSpec.swift */; };
15 | DF0E3FBB1E237E5900D00586 /* StringUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF0E3FB61E2378AF00D00586 /* StringUtil.swift */; };
16 | DF23DFCF1E220EDB0032641D /* Alamofire.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = DF23DFCE1E220EDB0032641D /* Alamofire.framework */; };
17 | DF23DFD61E220F250032641D /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = DF23DFD41E220F250032641D /* Nimble.framework */; };
18 | DF23DFD71E220F250032641D /* Quick.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = DF23DFD51E220F250032641D /* Quick.framework */; };
19 | DF23DFD91E2211A70032641D /* SearchResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF23DFD81E2211A70032641D /* SearchResultViewController.swift */; };
20 | DF23DFDB1E2218990032641D /* SearchResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF23DFDA1E2218990032641D /* SearchResultView.swift */; };
21 | DF23DFDD1E2219B10032641D /* SearchResultView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DF23DFDC1E2219B10032641D /* SearchResultView.xib */; };
22 | DF30726D1E1BA625005AA130 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF30726C1E1BA625005AA130 /* AppDelegate.swift */; };
23 | DF30726F1E1BA625005AA130 /* SearchSceneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF30726E1E1BA625005AA130 /* SearchSceneViewController.swift */; };
24 | DF3072741E1BA625005AA130 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DF3072731E1BA625005AA130 /* Assets.xcassets */; };
25 | DF3072771E1BA625005AA130 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DF3072751E1BA625005AA130 /* LaunchScreen.storyboard */; };
26 | DF3072901E1BE7D5005AA130 /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF30728F1E1BE7D5005AA130 /* AppCoordinator.swift */; };
27 | DF31C0531E1F27360053DB38 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF31C0521E1F27360053DB38 /* BaseViewController.swift */; };
28 | DF74B9B21E1C8EAB0028246C /* ReSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF30728D1E1BB2EA005AA130 /* ReSwift.framework */; };
29 | DF74B9B41E1C8F130028246C /* ReSwift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = DF30728D1E1BB2EA005AA130 /* ReSwift.framework */; };
30 | DF74B9B71E1C906A0028246C /* SearchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DF74B9B61E1C906A0028246C /* SearchView.xib */; };
31 | DF74B9B81E1C906A0028246C /* SearchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DF74B9B61E1C906A0028246C /* SearchView.xib */; };
32 | DF74B9BD1E1C91F00028246C /* XibBaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9BC1E1C91F00028246C /* XibBaseView.swift */; };
33 | DF74B9BE1E1C91F00028246C /* XibBaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9BC1E1C91F00028246C /* XibBaseView.swift */; };
34 | DF74B9C11E1C92230028246C /* colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9C01E1C92230028246C /* colors.swift */; };
35 | DF74B9C21E1C92230028246C /* colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9C01E1C92230028246C /* colors.swift */; };
36 | DF74B9C41E1C92310028246C /* fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9C31E1C92310028246C /* fonts.swift */; };
37 | DF74B9C51E1C92310028246C /* fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9C31E1C92310028246C /* fonts.swift */; };
38 | DF74B9C91E1CAF660028246C /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9C81E1CAF660028246C /* AppState.swift */; };
39 | DF74B9CA1E1CAF660028246C /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9C81E1CAF660028246C /* AppState.swift */; };
40 | DF74B9D21E1CCB590028246C /* PropertyActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9D11E1CCB590028246C /* PropertyActions.swift */; };
41 | DF74B9D31E1CCB590028246C /* PropertyActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9D11E1CCB590028246C /* PropertyActions.swift */; };
42 | DF74B9D81E1CDF680028246C /* AppReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9D71E1CDF680028246C /* AppReducer.swift */; };
43 | DF74B9D91E1CDF680028246C /* AppReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9D71E1CDF680028246C /* AppReducer.swift */; };
44 | DF74B9DB1E1CE2F70028246C /* LoadingActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9DA1E1CE2F70028246C /* LoadingActions.swift */; };
45 | DF74B9DC1E1CE2F70028246C /* LoadingActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9DA1E1CE2F70028246C /* LoadingActions.swift */; };
46 | DF74B9DE1E1CE3630028246C /* ErrorMessageActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9DD1E1CE3630028246C /* ErrorMessageActions.swift */; };
47 | DF74B9DF1E1CE3630028246C /* ErrorMessageActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9DD1E1CE3630028246C /* ErrorMessageActions.swift */; };
48 | DF74B9E21E1CF3EB0028246C /* PropertyApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9E11E1CF3EB0028246C /* PropertyApi.swift */; };
49 | DF74B9E31E1CF3EB0028246C /* PropertyApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF74B9E11E1CF3EB0028246C /* PropertyApi.swift */; };
50 | DF74B9E51E1CF7420028246C /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF74B9E41E1CF7420028246C /* Alamofire.framework */; };
51 | DFC1E6A11E714CFF00AB419F /* SearchSceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFC1E6A01E714CFF00AB419F /* SearchSceneCoordinator.swift */; };
52 | DFC1E6A31E714EA200AB419F /* SearchResultsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFC1E6A21E714EA200AB419F /* SearchResultsCoordinator.swift */; };
53 | DFC26C221E1F404700148AB5 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFC26C211E1F404700148AB5 /* SearchView.swift */; };
54 | DFC26C271E1F6F8A00148AB5 /* LocationTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFC26C261E1F6F8A00148AB5 /* LocationTracker.swift */; };
55 | DFF15E401E212BDC0072DACF /* LocationTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFC26C261E1F6F8A00148AB5 /* LocationTracker.swift */; };
56 | /* End PBXBuildFile section */
57 |
58 | /* Begin PBXContainerItemProxy section */
59 | DF30727E1E1BA625005AA130 /* PBXContainerItemProxy */ = {
60 | isa = PBXContainerItemProxy;
61 | containerPortal = DF3072611E1BA625005AA130 /* Project object */;
62 | proxyType = 1;
63 | remoteGlobalIDString = DF3072681E1BA625005AA130;
64 | remoteInfo = ReswiftAppCoordinatorDemo;
65 | };
66 | /* End PBXContainerItemProxy section */
67 |
68 | /* Begin PBXCopyFilesBuildPhase section */
69 | DF74B9B31E1C8EF30028246C /* CopyFiles */ = {
70 | isa = PBXCopyFilesBuildPhase;
71 | buildActionMask = 12;
72 | dstPath = "";
73 | dstSubfolderSpec = 16;
74 | files = (
75 | DF23DFD61E220F250032641D /* Nimble.framework in CopyFiles */,
76 | DF23DFD71E220F250032641D /* Quick.framework in CopyFiles */,
77 | DF23DFCF1E220EDB0032641D /* Alamofire.framework in CopyFiles */,
78 | DF74B9B41E1C8F130028246C /* ReSwift.framework in CopyFiles */,
79 | );
80 | runOnlyForDeploymentPostprocessing = 0;
81 | };
82 | /* End PBXCopyFilesBuildPhase section */
83 |
84 | /* Begin PBXFileReference section */
85 | DF0E3FAF1E2369BA00D00586 /* PropertyDetailSceneViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyDetailSceneViewController.swift; sourceTree = ""; };
86 | DF0E3FB11E236C0400D00586 /* PropertyDetailView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PropertyDetailView.xib; sourceTree = ""; };
87 | DF0E3FB31E236C1900D00586 /* PropertyDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyDetailView.swift; sourceTree = ""; };
88 | DF0E3FB61E2378AF00D00586 /* StringUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringUtil.swift; sourceTree = ""; };
89 | DF0E3FB91E237C9F00D00586 /* StringUtilSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringUtilSpec.swift; sourceTree = ""; };
90 | DF23DFCE1E220EDB0032641D /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = ""; };
91 | DF23DFD41E220F250032641D /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/iOS/Nimble.framework; sourceTree = ""; };
92 | DF23DFD51E220F250032641D /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quick.framework; path = Carthage/Build/iOS/Quick.framework; sourceTree = ""; };
93 | DF23DFD81E2211A70032641D /* SearchResultViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchResultViewController.swift; sourceTree = ""; };
94 | DF23DFDA1E2218990032641D /* SearchResultView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchResultView.swift; sourceTree = ""; };
95 | DF23DFDC1E2219B10032641D /* SearchResultView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SearchResultView.xib; sourceTree = ""; };
96 | DF3072691E1BA625005AA130 /* ReswiftAppCoordinatorDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReswiftAppCoordinatorDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
97 | DF30726C1E1BA625005AA130 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
98 | DF30726E1E1BA625005AA130 /* SearchSceneViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSceneViewController.swift; sourceTree = ""; };
99 | DF3072731E1BA625005AA130 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
100 | DF3072761E1BA625005AA130 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
101 | DF3072781E1BA625005AA130 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
102 | DF30727D1E1BA625005AA130 /* ReswiftAppCoordinatorDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReswiftAppCoordinatorDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
103 | DF3072831E1BA625005AA130 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
104 | DF30728D1E1BB2EA005AA130 /* ReSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReSwift.framework; path = Carthage/Build/iOS/ReSwift.framework; sourceTree = ""; };
105 | DF30728F1E1BE7D5005AA130 /* AppCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = ""; };
106 | DF31C0521E1F27360053DB38 /* BaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; };
107 | DF74B9B61E1C906A0028246C /* SearchView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SearchView.xib; sourceTree = ""; };
108 | DF74B9BC1E1C91F00028246C /* XibBaseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XibBaseView.swift; sourceTree = ""; };
109 | DF74B9C01E1C92230028246C /* colors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = colors.swift; sourceTree = ""; };
110 | DF74B9C31E1C92310028246C /* fonts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = fonts.swift; sourceTree = ""; };
111 | DF74B9C81E1CAF660028246C /* AppState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; };
112 | DF74B9D11E1CCB590028246C /* PropertyActions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyActions.swift; sourceTree = ""; };
113 | DF74B9D71E1CDF680028246C /* AppReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppReducer.swift; sourceTree = ""; };
114 | DF74B9DA1E1CE2F70028246C /* LoadingActions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingActions.swift; sourceTree = ""; };
115 | DF74B9DD1E1CE3630028246C /* ErrorMessageActions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorMessageActions.swift; sourceTree = ""; };
116 | DF74B9E11E1CF3EB0028246C /* PropertyApi.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyApi.swift; sourceTree = ""; };
117 | DF74B9E41E1CF7420028246C /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = ""; };
118 | DFC1E6A01E714CFF00AB419F /* SearchSceneCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchSceneCoordinator.swift; sourceTree = ""; };
119 | DFC1E6A21E714EA200AB419F /* SearchResultsCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchResultsCoordinator.swift; sourceTree = ""; };
120 | DFC26C211E1F404700148AB5 /* SearchView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; };
121 | DFC26C261E1F6F8A00148AB5 /* LocationTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationTracker.swift; sourceTree = ""; };
122 | /* End PBXFileReference section */
123 |
124 | /* Begin PBXFrameworksBuildPhase section */
125 | DF3072661E1BA625005AA130 /* Frameworks */ = {
126 | isa = PBXFrameworksBuildPhase;
127 | buildActionMask = 2147483647;
128 | files = (
129 | DF74B9E51E1CF7420028246C /* Alamofire.framework in Frameworks */,
130 | DF74B9B21E1C8EAB0028246C /* ReSwift.framework in Frameworks */,
131 | );
132 | runOnlyForDeploymentPostprocessing = 0;
133 | };
134 | DF30727A1E1BA625005AA130 /* Frameworks */ = {
135 | isa = PBXFrameworksBuildPhase;
136 | buildActionMask = 2147483647;
137 | files = (
138 | );
139 | runOnlyForDeploymentPostprocessing = 0;
140 | };
141 | /* End PBXFrameworksBuildPhase section */
142 |
143 | /* Begin PBXGroup section */
144 | DF0E3FB51E23789F00D00586 /* Utilities */ = {
145 | isa = PBXGroup;
146 | children = (
147 | DF0E3FB61E2378AF00D00586 /* StringUtil.swift */,
148 | );
149 | name = Utilities;
150 | sourceTree = "";
151 | };
152 | DF0E3FB81E237C8400D00586 /* Utilities */ = {
153 | isa = PBXGroup;
154 | children = (
155 | DF0E3FB91E237C9F00D00586 /* StringUtilSpec.swift */,
156 | );
157 | name = Utilities;
158 | sourceTree = "";
159 | };
160 | DF3072601E1BA625005AA130 = {
161 | isa = PBXGroup;
162 | children = (
163 | DF23DFD41E220F250032641D /* Nimble.framework */,
164 | DF23DFD51E220F250032641D /* Quick.framework */,
165 | DF23DFCE1E220EDB0032641D /* Alamofire.framework */,
166 | DF30726B1E1BA625005AA130 /* ReswiftAppCoordinatorDemo */,
167 | DF3072801E1BA625005AA130 /* ReswiftAppCoordinatorDemoTests */,
168 | DF30726A1E1BA625005AA130 /* Products */,
169 | DF30728C1E1BB2EA005AA130 /* Frameworks */,
170 | );
171 | sourceTree = "";
172 | };
173 | DF30726A1E1BA625005AA130 /* Products */ = {
174 | isa = PBXGroup;
175 | children = (
176 | DF3072691E1BA625005AA130 /* ReswiftAppCoordinatorDemo.app */,
177 | DF30727D1E1BA625005AA130 /* ReswiftAppCoordinatorDemoTests.xctest */,
178 | );
179 | name = Products;
180 | sourceTree = "";
181 | };
182 | DF30726B1E1BA625005AA130 /* ReswiftAppCoordinatorDemo */ = {
183 | isa = PBXGroup;
184 | children = (
185 | DFC1E69F1E714CE000AB419F /* Coordinators */,
186 | DF0E3FB51E23789F00D00586 /* Utilities */,
187 | DFC26C251E1F6F3500148AB5 /* Sensor */,
188 | DF74B9BF1E1C92120028246C /* Themes */,
189 | DF74B9C71E1CADE10028246C /* Reducers */,
190 | DF74B9C61E1CADBE0028246C /* Actions */,
191 | DF74B9E01E1CF3BF0028246C /* API */,
192 | DF74B9B51E1C90210028246C /* Views */,
193 | DF30726C1E1BA625005AA130 /* AppDelegate.swift */,
194 | DF30728F1E1BE7D5005AA130 /* AppCoordinator.swift */,
195 | DF74B9C81E1CAF660028246C /* AppState.swift */,
196 | DF3072731E1BA625005AA130 /* Assets.xcassets */,
197 | DF3072751E1BA625005AA130 /* LaunchScreen.storyboard */,
198 | DF3072781E1BA625005AA130 /* Info.plist */,
199 | );
200 | path = ReswiftAppCoordinatorDemo;
201 | sourceTree = "";
202 | };
203 | DF3072801E1BA625005AA130 /* ReswiftAppCoordinatorDemoTests */ = {
204 | isa = PBXGroup;
205 | children = (
206 | DF0E3FB81E237C8400D00586 /* Utilities */,
207 | DF3072831E1BA625005AA130 /* Info.plist */,
208 | );
209 | path = ReswiftAppCoordinatorDemoTests;
210 | sourceTree = "";
211 | };
212 | DF30728C1E1BB2EA005AA130 /* Frameworks */ = {
213 | isa = PBXGroup;
214 | children = (
215 | DF74B9E41E1CF7420028246C /* Alamofire.framework */,
216 | DF30728D1E1BB2EA005AA130 /* ReSwift.framework */,
217 | );
218 | name = Frameworks;
219 | sourceTree = "";
220 | };
221 | DF74B9B51E1C90210028246C /* Views */ = {
222 | isa = PBXGroup;
223 | children = (
224 | DFC26C241E1F406400148AB5 /* BaseViews */,
225 | DF30726E1E1BA625005AA130 /* SearchSceneViewController.swift */,
226 | DFC26C211E1F404700148AB5 /* SearchView.swift */,
227 | DF74B9B61E1C906A0028246C /* SearchView.xib */,
228 | DF23DFD81E2211A70032641D /* SearchResultViewController.swift */,
229 | DF23DFDA1E2218990032641D /* SearchResultView.swift */,
230 | DF23DFDC1E2219B10032641D /* SearchResultView.xib */,
231 | DF0E3FAF1E2369BA00D00586 /* PropertyDetailSceneViewController.swift */,
232 | DF0E3FB31E236C1900D00586 /* PropertyDetailView.swift */,
233 | DF0E3FB11E236C0400D00586 /* PropertyDetailView.xib */,
234 | );
235 | name = Views;
236 | sourceTree = "";
237 | };
238 | DF74B9BF1E1C92120028246C /* Themes */ = {
239 | isa = PBXGroup;
240 | children = (
241 | DF74B9C01E1C92230028246C /* colors.swift */,
242 | DF74B9C31E1C92310028246C /* fonts.swift */,
243 | );
244 | name = Themes;
245 | sourceTree = "";
246 | };
247 | DF74B9C61E1CADBE0028246C /* Actions */ = {
248 | isa = PBXGroup;
249 | children = (
250 | DF74B9D11E1CCB590028246C /* PropertyActions.swift */,
251 | DF74B9DA1E1CE2F70028246C /* LoadingActions.swift */,
252 | DF74B9DD1E1CE3630028246C /* ErrorMessageActions.swift */,
253 | );
254 | name = Actions;
255 | sourceTree = "";
256 | };
257 | DF74B9C71E1CADE10028246C /* Reducers */ = {
258 | isa = PBXGroup;
259 | children = (
260 | DF74B9D71E1CDF680028246C /* AppReducer.swift */,
261 | );
262 | name = Reducers;
263 | sourceTree = "";
264 | };
265 | DF74B9E01E1CF3BF0028246C /* API */ = {
266 | isa = PBXGroup;
267 | children = (
268 | DF74B9E11E1CF3EB0028246C /* PropertyApi.swift */,
269 | );
270 | name = API;
271 | sourceTree = "";
272 | };
273 | DFC1E69F1E714CE000AB419F /* Coordinators */ = {
274 | isa = PBXGroup;
275 | children = (
276 | DFC1E6A01E714CFF00AB419F /* SearchSceneCoordinator.swift */,
277 | DFC1E6A21E714EA200AB419F /* SearchResultsCoordinator.swift */,
278 | );
279 | name = Coordinators;
280 | sourceTree = "";
281 | };
282 | DFC26C241E1F406400148AB5 /* BaseViews */ = {
283 | isa = PBXGroup;
284 | children = (
285 | DF74B9BC1E1C91F00028246C /* XibBaseView.swift */,
286 | DF31C0521E1F27360053DB38 /* BaseViewController.swift */,
287 | );
288 | name = BaseViews;
289 | sourceTree = "";
290 | };
291 | DFC26C251E1F6F3500148AB5 /* Sensor */ = {
292 | isa = PBXGroup;
293 | children = (
294 | DFC26C261E1F6F8A00148AB5 /* LocationTracker.swift */,
295 | );
296 | name = Sensor;
297 | sourceTree = "";
298 | };
299 | /* End PBXGroup section */
300 |
301 | /* Begin PBXNativeTarget section */
302 | DF3072681E1BA625005AA130 /* ReswiftAppCoordinatorDemo */ = {
303 | isa = PBXNativeTarget;
304 | buildConfigurationList = DF3072861E1BA625005AA130 /* Build configuration list for PBXNativeTarget "ReswiftAppCoordinatorDemo" */;
305 | buildPhases = (
306 | DF3072651E1BA625005AA130 /* Sources */,
307 | DF3072661E1BA625005AA130 /* Frameworks */,
308 | DF3072671E1BA625005AA130 /* Resources */,
309 | DF74B9B31E1C8EF30028246C /* CopyFiles */,
310 | );
311 | buildRules = (
312 | );
313 | dependencies = (
314 | );
315 | name = ReswiftAppCoordinatorDemo;
316 | productName = ReswiftAppCoordinatorDemo;
317 | productReference = DF3072691E1BA625005AA130 /* ReswiftAppCoordinatorDemo.app */;
318 | productType = "com.apple.product-type.application";
319 | };
320 | DF30727C1E1BA625005AA130 /* ReswiftAppCoordinatorDemoTests */ = {
321 | isa = PBXNativeTarget;
322 | buildConfigurationList = DF3072891E1BA625005AA130 /* Build configuration list for PBXNativeTarget "ReswiftAppCoordinatorDemoTests" */;
323 | buildPhases = (
324 | DF3072791E1BA625005AA130 /* Sources */,
325 | DF30727A1E1BA625005AA130 /* Frameworks */,
326 | DF30727B1E1BA625005AA130 /* Resources */,
327 | );
328 | buildRules = (
329 | );
330 | dependencies = (
331 | DF30727F1E1BA625005AA130 /* PBXTargetDependency */,
332 | );
333 | name = ReswiftAppCoordinatorDemoTests;
334 | productName = ReswiftAppCoordinatorDemoTests;
335 | productReference = DF30727D1E1BA625005AA130 /* ReswiftAppCoordinatorDemoTests.xctest */;
336 | productType = "com.apple.product-type.bundle.unit-test";
337 | };
338 | /* End PBXNativeTarget section */
339 |
340 | /* Begin PBXProject section */
341 | DF3072611E1BA625005AA130 /* Project object */ = {
342 | isa = PBXProject;
343 | attributes = {
344 | LastSwiftUpdateCheck = 0810;
345 | LastUpgradeCheck = 0810;
346 | ORGANIZATIONNAME = xianlinbox;
347 | TargetAttributes = {
348 | DF3072681E1BA625005AA130 = {
349 | CreatedOnToolsVersion = 8.1;
350 | DevelopmentTeam = TX44MTV4A5;
351 | ProvisioningStyle = Automatic;
352 | };
353 | DF30727C1E1BA625005AA130 = {
354 | CreatedOnToolsVersion = 8.1;
355 | ProvisioningStyle = Automatic;
356 | TestTargetID = DF3072681E1BA625005AA130;
357 | };
358 | };
359 | };
360 | buildConfigurationList = DF3072641E1BA625005AA130 /* Build configuration list for PBXProject "ReswiftAppCoordinatorDemo" */;
361 | compatibilityVersion = "Xcode 3.2";
362 | developmentRegion = English;
363 | hasScannedForEncodings = 0;
364 | knownRegions = (
365 | en,
366 | Base,
367 | );
368 | mainGroup = DF3072601E1BA625005AA130;
369 | productRefGroup = DF30726A1E1BA625005AA130 /* Products */;
370 | projectDirPath = "";
371 | projectRoot = "";
372 | targets = (
373 | DF3072681E1BA625005AA130 /* ReswiftAppCoordinatorDemo */,
374 | DF30727C1E1BA625005AA130 /* ReswiftAppCoordinatorDemoTests */,
375 | );
376 | };
377 | /* End PBXProject section */
378 |
379 | /* Begin PBXResourcesBuildPhase section */
380 | DF3072671E1BA625005AA130 /* Resources */ = {
381 | isa = PBXResourcesBuildPhase;
382 | buildActionMask = 2147483647;
383 | files = (
384 | DF0E3FB21E236C0400D00586 /* PropertyDetailView.xib in Resources */,
385 | DF23DFDD1E2219B10032641D /* SearchResultView.xib in Resources */,
386 | DF74B9B71E1C906A0028246C /* SearchView.xib in Resources */,
387 | DF3072771E1BA625005AA130 /* LaunchScreen.storyboard in Resources */,
388 | DF3072741E1BA625005AA130 /* Assets.xcassets in Resources */,
389 | );
390 | runOnlyForDeploymentPostprocessing = 0;
391 | };
392 | DF30727B1E1BA625005AA130 /* Resources */ = {
393 | isa = PBXResourcesBuildPhase;
394 | buildActionMask = 2147483647;
395 | files = (
396 | DF74B9B81E1C906A0028246C /* SearchView.xib in Resources */,
397 | );
398 | runOnlyForDeploymentPostprocessing = 0;
399 | };
400 | /* End PBXResourcesBuildPhase section */
401 |
402 | /* Begin PBXSourcesBuildPhase section */
403 | DF3072651E1BA625005AA130 /* Sources */ = {
404 | isa = PBXSourcesBuildPhase;
405 | buildActionMask = 2147483647;
406 | files = (
407 | DF31C0531E1F27360053DB38 /* BaseViewController.swift in Sources */,
408 | DF74B9BD1E1C91F00028246C /* XibBaseView.swift in Sources */,
409 | DF74B9D21E1CCB590028246C /* PropertyActions.swift in Sources */,
410 | DF74B9C11E1C92230028246C /* colors.swift in Sources */,
411 | DF74B9D81E1CDF680028246C /* AppReducer.swift in Sources */,
412 | DF74B9DE1E1CE3630028246C /* ErrorMessageActions.swift in Sources */,
413 | DFC1E6A11E714CFF00AB419F /* SearchSceneCoordinator.swift in Sources */,
414 | DF74B9DB1E1CE2F70028246C /* LoadingActions.swift in Sources */,
415 | DF74B9C91E1CAF660028246C /* AppState.swift in Sources */,
416 | DFC1E6A31E714EA200AB419F /* SearchResultsCoordinator.swift in Sources */,
417 | DF74B9E21E1CF3EB0028246C /* PropertyApi.swift in Sources */,
418 | DF3072901E1BE7D5005AA130 /* AppCoordinator.swift in Sources */,
419 | DFC26C221E1F404700148AB5 /* SearchView.swift in Sources */,
420 | DF30726F1E1BA625005AA130 /* SearchSceneViewController.swift in Sources */,
421 | DF23DFDB1E2218990032641D /* SearchResultView.swift in Sources */,
422 | DF0E3FB41E236C1900D00586 /* PropertyDetailView.swift in Sources */,
423 | DF74B9C41E1C92310028246C /* fonts.swift in Sources */,
424 | DF30726D1E1BA625005AA130 /* AppDelegate.swift in Sources */,
425 | DF23DFD91E2211A70032641D /* SearchResultViewController.swift in Sources */,
426 | DFC26C271E1F6F8A00148AB5 /* LocationTracker.swift in Sources */,
427 | DF0E3FB01E2369BA00D00586 /* PropertyDetailSceneViewController.swift in Sources */,
428 | DF0E3FB71E2378AF00D00586 /* StringUtil.swift in Sources */,
429 | );
430 | runOnlyForDeploymentPostprocessing = 0;
431 | };
432 | DF3072791E1BA625005AA130 /* Sources */ = {
433 | isa = PBXSourcesBuildPhase;
434 | buildActionMask = 2147483647;
435 | files = (
436 | DF0E3FBA1E237C9F00D00586 /* StringUtilSpec.swift in Sources */,
437 | DF74B9C51E1C92310028246C /* fonts.swift in Sources */,
438 | DF74B9E31E1CF3EB0028246C /* PropertyApi.swift in Sources */,
439 | DF74B9CA1E1CAF660028246C /* AppState.swift in Sources */,
440 | DF74B9BE1E1C91F00028246C /* XibBaseView.swift in Sources */,
441 | DF74B9DC1E1CE2F70028246C /* LoadingActions.swift in Sources */,
442 | DF74B9C21E1C92230028246C /* colors.swift in Sources */,
443 | DFF15E401E212BDC0072DACF /* LocationTracker.swift in Sources */,
444 | DF0E3FBB1E237E5900D00586 /* StringUtil.swift in Sources */,
445 | DF74B9D31E1CCB590028246C /* PropertyActions.swift in Sources */,
446 | DF74B9DF1E1CE3630028246C /* ErrorMessageActions.swift in Sources */,
447 | DF74B9D91E1CDF680028246C /* AppReducer.swift in Sources */,
448 | );
449 | runOnlyForDeploymentPostprocessing = 0;
450 | };
451 | /* End PBXSourcesBuildPhase section */
452 |
453 | /* Begin PBXTargetDependency section */
454 | DF30727F1E1BA625005AA130 /* PBXTargetDependency */ = {
455 | isa = PBXTargetDependency;
456 | target = DF3072681E1BA625005AA130 /* ReswiftAppCoordinatorDemo */;
457 | targetProxy = DF30727E1E1BA625005AA130 /* PBXContainerItemProxy */;
458 | };
459 | /* End PBXTargetDependency section */
460 |
461 | /* Begin PBXVariantGroup section */
462 | DF3072751E1BA625005AA130 /* LaunchScreen.storyboard */ = {
463 | isa = PBXVariantGroup;
464 | children = (
465 | DF3072761E1BA625005AA130 /* Base */,
466 | );
467 | name = LaunchScreen.storyboard;
468 | sourceTree = "";
469 | };
470 | /* End PBXVariantGroup section */
471 |
472 | /* Begin XCBuildConfiguration section */
473 | DF3072841E1BA625005AA130 /* Debug */ = {
474 | isa = XCBuildConfiguration;
475 | buildSettings = {
476 | ALWAYS_SEARCH_USER_PATHS = NO;
477 | CLANG_ANALYZER_NONNULL = YES;
478 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
479 | CLANG_CXX_LIBRARY = "libc++";
480 | CLANG_ENABLE_MODULES = YES;
481 | CLANG_ENABLE_OBJC_ARC = YES;
482 | CLANG_WARN_BOOL_CONVERSION = YES;
483 | CLANG_WARN_CONSTANT_CONVERSION = YES;
484 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
485 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
486 | CLANG_WARN_EMPTY_BODY = YES;
487 | CLANG_WARN_ENUM_CONVERSION = YES;
488 | CLANG_WARN_INFINITE_RECURSION = YES;
489 | CLANG_WARN_INT_CONVERSION = YES;
490 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
491 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
492 | CLANG_WARN_UNREACHABLE_CODE = YES;
493 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
494 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
495 | COPY_PHASE_STRIP = NO;
496 | DEBUG_INFORMATION_FORMAT = dwarf;
497 | ENABLE_STRICT_OBJC_MSGSEND = YES;
498 | ENABLE_TESTABILITY = YES;
499 | GCC_C_LANGUAGE_STANDARD = gnu99;
500 | GCC_DYNAMIC_NO_PIC = NO;
501 | GCC_NO_COMMON_BLOCKS = YES;
502 | GCC_OPTIMIZATION_LEVEL = 0;
503 | GCC_PREPROCESSOR_DEFINITIONS = (
504 | "DEBUG=1",
505 | "$(inherited)",
506 | );
507 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
508 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
509 | GCC_WARN_UNDECLARED_SELECTOR = YES;
510 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
511 | GCC_WARN_UNUSED_FUNCTION = YES;
512 | GCC_WARN_UNUSED_VARIABLE = YES;
513 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
514 | MTL_ENABLE_DEBUG_INFO = YES;
515 | ONLY_ACTIVE_ARCH = YES;
516 | SDKROOT = iphoneos;
517 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
518 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
519 | };
520 | name = Debug;
521 | };
522 | DF3072851E1BA625005AA130 /* Release */ = {
523 | isa = XCBuildConfiguration;
524 | buildSettings = {
525 | ALWAYS_SEARCH_USER_PATHS = NO;
526 | CLANG_ANALYZER_NONNULL = YES;
527 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
528 | CLANG_CXX_LIBRARY = "libc++";
529 | CLANG_ENABLE_MODULES = YES;
530 | CLANG_ENABLE_OBJC_ARC = YES;
531 | CLANG_WARN_BOOL_CONVERSION = YES;
532 | CLANG_WARN_CONSTANT_CONVERSION = YES;
533 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
534 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
535 | CLANG_WARN_EMPTY_BODY = YES;
536 | CLANG_WARN_ENUM_CONVERSION = YES;
537 | CLANG_WARN_INFINITE_RECURSION = YES;
538 | CLANG_WARN_INT_CONVERSION = YES;
539 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
540 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
541 | CLANG_WARN_UNREACHABLE_CODE = YES;
542 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
543 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
544 | COPY_PHASE_STRIP = NO;
545 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
546 | ENABLE_NS_ASSERTIONS = NO;
547 | ENABLE_STRICT_OBJC_MSGSEND = YES;
548 | GCC_C_LANGUAGE_STANDARD = gnu99;
549 | GCC_NO_COMMON_BLOCKS = YES;
550 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
551 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
552 | GCC_WARN_UNDECLARED_SELECTOR = YES;
553 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
554 | GCC_WARN_UNUSED_FUNCTION = YES;
555 | GCC_WARN_UNUSED_VARIABLE = YES;
556 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
557 | MTL_ENABLE_DEBUG_INFO = NO;
558 | SDKROOT = iphoneos;
559 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
560 | VALIDATE_PRODUCT = YES;
561 | };
562 | name = Release;
563 | };
564 | DF3072871E1BA625005AA130 /* Debug */ = {
565 | isa = XCBuildConfiguration;
566 | buildSettings = {
567 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
568 | DEVELOPMENT_TEAM = TX44MTV4A5;
569 | FRAMEWORK_SEARCH_PATHS = (
570 | "$(inherited)",
571 | "$(PROJECT_DIR)/Carthage/Build/iOS",
572 | );
573 | INFOPLIST_FILE = ReswiftAppCoordinatorDemo/Info.plist;
574 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
575 | PRODUCT_BUNDLE_IDENTIFIER = com.xianlinbox.ReswiftAppCoordinatorDemo;
576 | PRODUCT_NAME = "$(TARGET_NAME)";
577 | SWIFT_VERSION = 3.0;
578 | };
579 | name = Debug;
580 | };
581 | DF3072881E1BA625005AA130 /* Release */ = {
582 | isa = XCBuildConfiguration;
583 | buildSettings = {
584 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
585 | DEVELOPMENT_TEAM = TX44MTV4A5;
586 | FRAMEWORK_SEARCH_PATHS = (
587 | "$(inherited)",
588 | "$(PROJECT_DIR)/Carthage/Build/iOS",
589 | );
590 | INFOPLIST_FILE = ReswiftAppCoordinatorDemo/Info.plist;
591 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
592 | PRODUCT_BUNDLE_IDENTIFIER = com.xianlinbox.ReswiftAppCoordinatorDemo;
593 | PRODUCT_NAME = "$(TARGET_NAME)";
594 | SWIFT_VERSION = 3.0;
595 | };
596 | name = Release;
597 | };
598 | DF30728A1E1BA625005AA130 /* Debug */ = {
599 | isa = XCBuildConfiguration;
600 | buildSettings = {
601 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
602 | BUNDLE_LOADER = "$(TEST_HOST)";
603 | INFOPLIST_FILE = ReswiftAppCoordinatorDemoTests/Info.plist;
604 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
605 | PRODUCT_BUNDLE_IDENTIFIER = com.xianlinbox.ReswiftAppCoordinatorDemoTests;
606 | PRODUCT_NAME = "$(TARGET_NAME)";
607 | SWIFT_VERSION = 3.0;
608 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReswiftAppCoordinatorDemo.app/ReswiftAppCoordinatorDemo";
609 | };
610 | name = Debug;
611 | };
612 | DF30728B1E1BA625005AA130 /* Release */ = {
613 | isa = XCBuildConfiguration;
614 | buildSettings = {
615 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
616 | BUNDLE_LOADER = "$(TEST_HOST)";
617 | INFOPLIST_FILE = ReswiftAppCoordinatorDemoTests/Info.plist;
618 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
619 | PRODUCT_BUNDLE_IDENTIFIER = com.xianlinbox.ReswiftAppCoordinatorDemoTests;
620 | PRODUCT_NAME = "$(TARGET_NAME)";
621 | SWIFT_VERSION = 3.0;
622 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReswiftAppCoordinatorDemo.app/ReswiftAppCoordinatorDemo";
623 | };
624 | name = Release;
625 | };
626 | /* End XCBuildConfiguration section */
627 |
628 | /* Begin XCConfigurationList section */
629 | DF3072641E1BA625005AA130 /* Build configuration list for PBXProject "ReswiftAppCoordinatorDemo" */ = {
630 | isa = XCConfigurationList;
631 | buildConfigurations = (
632 | DF3072841E1BA625005AA130 /* Debug */,
633 | DF3072851E1BA625005AA130 /* Release */,
634 | );
635 | defaultConfigurationIsVisible = 0;
636 | defaultConfigurationName = Release;
637 | };
638 | DF3072861E1BA625005AA130 /* Build configuration list for PBXNativeTarget "ReswiftAppCoordinatorDemo" */ = {
639 | isa = XCConfigurationList;
640 | buildConfigurations = (
641 | DF3072871E1BA625005AA130 /* Debug */,
642 | DF3072881E1BA625005AA130 /* Release */,
643 | );
644 | defaultConfigurationIsVisible = 0;
645 | defaultConfigurationName = Release;
646 | };
647 | DF3072891E1BA625005AA130 /* Build configuration list for PBXNativeTarget "ReswiftAppCoordinatorDemoTests" */ = {
648 | isa = XCConfigurationList;
649 | buildConfigurations = (
650 | DF30728A1E1BA625005AA130 /* Debug */,
651 | DF30728B1E1BA625005AA130 /* Release */,
652 | );
653 | defaultConfigurationIsVisible = 0;
654 | defaultConfigurationName = Release;
655 | };
656 | /* End XCConfigurationList section */
657 | };
658 | rootObject = DF3072611E1BA625005AA130 /* Project object */;
659 | }
660 |
--------------------------------------------------------------------------------