Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
1
1weather
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
1weather
Commits
ce879c83
Commit
ce879c83
authored
Dec 03, 2020
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on Locations UI logic
parent
f0f001bc
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
444 additions
and
118 deletions
+444
-118
1Weather.xcodeproj/project.pbxproj
+17
-1
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
+0
-0
1Weather/Extensions/UIViewController+Alert.swift
+20
-0
1Weather/Managers/PopularCitiesManager.swift
+38
-0
1Weather/UI/Helpers/ThemeManager.swift
+1
-0
1Weather/UI/Models/WdtLocation.swift
+21
-7
1Weather/UI/Models/WeatherUpdateManager.swift
+46
-0
1Weather/UI/View controllers/Location/Cells/CityCell.swift
+30
-5
1Weather/UI/View controllers/Location/LocationViewController.swift
+155
-22
1Weather/UI/View controllers/Location/LocationsViewModel.swift
+76
-34
1weather_IOS.sketch
+0
-0
Pods/Pods.xcodeproj/project.pbxproj
+6
-9
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/AlgoliaSearchClient.xcscheme
+11
-13
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/Logging.xcscheme
+11
-13
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/Pods-1Weather.xcscheme
+1
-1
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/SnapKit.xcscheme
+11
-13
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
ce879c83
...
...
@@ -24,6 +24,8 @@
CD6B303B2572680C004B34B3
/* SelfSizingButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6B303A2572680C004B34B3
/* SelfSizingButton.swift */
;
};
CD6B303E25726960004B34B3
/* ThemeProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6B303D25726960004B34B3
/* ThemeProtocol.swift */
;
};
CD6B304325726AD1004B34B3
/* DefaultTheme.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6B304225726AD1004B34B3
/* DefaultTheme.swift */
;
};
CD8091772578D73F003541A4
/* PopularCitiesManager.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD8091762578D73F003541A4
/* PopularCitiesManager.swift */
;
};
CD80917B2578E4A8003541A4
/* UIViewController+Alert.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
;
};
CDA69B2C2574F3C800CB6409
/* CityCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA69B2B2574F3C800CB6409
/* CityCell.swift */
;
};
CDA69B30257500E200CB6409
/* GeoNamesPlace.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA69B2F257500E200CB6409
/* GeoNamesPlace.swift */
;
};
CDA69B3325750D3400CB6409
/* LocationsViewModel.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA69B3225750D3400CB6409
/* LocationsViewModel.swift */
;
};
...
...
@@ -57,6 +59,8 @@
CD6B303A2572680C004B34B3
/* SelfSizingButton.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
SelfSizingButton.swift
;
sourceTree
=
"<group>"
;
};
CD6B303D25726960004B34B3
/* ThemeProtocol.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ThemeProtocol.swift
;
sourceTree
=
"<group>"
;
};
CD6B304225726AD1004B34B3
/* DefaultTheme.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
DefaultTheme.swift
;
sourceTree
=
"<group>"
;
};
CD8091762578D73F003541A4
/* PopularCitiesManager.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PopularCitiesManager.swift
;
sourceTree
=
"<group>"
;
};
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"UIViewController+Alert.swift"
;
sourceTree
=
"<group>"
;
};
CDA69B2B2574F3C800CB6409
/* CityCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CityCell.swift
;
sourceTree
=
"<group>"
;
};
CDA69B2F257500E200CB6409
/* GeoNamesPlace.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
GeoNamesPlace.swift
;
sourceTree
=
"<group>"
;
};
CDA69B3225750D3400CB6409
/* LocationsViewModel.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
LocationsViewModel.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -112,6 +116,7 @@
isa
=
PBXGroup
;
children
=
(
CD1237DA255D5DFA00C98139
/* PG.playground */
,
CD8091752578D726003541A4
/* Managers */
,
CDD0F1DC2572400200CF5017
/* UI */
,
CD1237EF255D838600C98139
/* Extensions */
,
CDD0F1E2257240DA00CF5017
/* Resources */
,
...
...
@@ -138,6 +143,7 @@
children
=
(
CD1237F0255D83C500C98139
/* UIColor+Hex.swift */
,
CD6B3035257262C2004B34B3
/* UIColor+Highlight.swift */
,
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
,
);
path
=
Extensions
;
sourceTree
=
"<group>"
;
...
...
@@ -167,6 +173,14 @@
path
=
Themes
;
sourceTree
=
"<group>"
;
};
CD8091752578D726003541A4
/* Managers */
=
{
isa
=
PBXGroup
;
children
=
(
CD8091762578D73F003541A4
/* PopularCitiesManager.swift */
,
);
path
=
Managers
;
sourceTree
=
"<group>"
;
};
CDA69B2A2574F3A700CB6409
/* Cells */
=
{
isa
=
PBXGroup
;
children
=
(
...
...
@@ -275,7 +289,7 @@
isa
=
PBXProject
;
attributes
=
{
LastSwiftUpdateCheck
=
1210
;
LastUpgradeCheck
=
12
1
0
;
LastUpgradeCheck
=
12
2
0
;
TargetAttributes
=
{
CD1237BE255D5C5900C98139
=
{
CreatedOnToolsVersion
=
12.1
;
...
...
@@ -379,7 +393,9 @@
870880222578ED190076BFB1
/* WdtHourSummary.swift in Sources */
,
CD6B303E25726960004B34B3
/* ThemeProtocol.swift in Sources */
,
CD6B303B2572680C004B34B3
/* SelfSizingButton.swift in Sources */
,
CD8091772578D73F003541A4
/* PopularCitiesManager.swift in Sources */
,
CDA69B2C2574F3C800CB6409
/* CityCell.swift in Sources */
,
CD80917B2578E4A8003541A4
/* UIViewController+Alert.swift in Sources */
,
CD1237DE255D612300C98139
/* CurrentForecastCell.swift in Sources */
,
CEAD00A12577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift in Sources */
,
);
...
...
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
View file @
ce879c83
No preview for this file type
1Weather/Extensions/UIViewController+Alert.swift
0 → 100644
View file @
ce879c83
//
// UIViewController+Alert.swift
// 1Weather
//
// Created by Dmitry Stepanets on 03.12.2020.
//
import
UIKit
extension
UIViewController
{
func
showAlert
(
withTitle
title
:
String
?,
message
:
String
?)
{
guard
message
!=
nil
,
message
?
.
isEmpty
==
false
else
{
return
}
DispatchQueue
.
main
.
async
{
let
alert
=
UIAlertController
(
title
:
title
,
message
:
message
,
preferredStyle
:
.
alert
)
alert
.
addAction
(
UIAlertAction
(
title
:
"Cancel"
,
style
:
.
cancel
))
self
.
present
(
alert
,
animated
:
true
)
}
}
}
1Weather/Managers/PopularCitiesManager.swift
0 → 100644
View file @
ce879c83
//
// PopularCitiesManager.swift
// 1Weather
//
// Created by Dmitry Stepanets on 03.12.2020.
//
import
UIKit
class
PopularCitiesManager
{
func
fetchPopularCities
(
completion
:
@escaping
(
_
result
:
Result
<
[
GeoNamesPlace
],
Error
>
)
->
Void
)
{
let
ny
=
GeoNamesPlace
()
ny
.
city
=
"New York"
ny
.
stateCode
=
"00001"
ny
.
state
=
"NY"
ny
.
country
=
"USA"
let
chicago
=
GeoNamesPlace
()
chicago
.
city
=
"Chicago"
chicago
.
stateCode
=
"00002"
chicago
.
state
=
"IL"
chicago
.
country
=
"USA"
let
wg
=
GeoNamesPlace
()
wg
.
city
=
"Washington DC"
wg
.
stateCode
=
"00003"
wg
.
state
=
"DC"
wg
.
country
=
"USA"
let
boston
=
GeoNamesPlace
()
boston
.
city
=
"Boston"
boston
.
stateCode
=
"00004"
boston
.
state
=
"MA"
boston
.
country
=
"USA"
completion
(
.
success
([
ny
,
chicago
,
wg
,
boston
]))
}
}
1Weather/UI/Helpers/ThemeManager.swift
View file @
ce879c83
...
...
@@ -14,6 +14,7 @@ public struct ThemeManager {
static
let
citySelected
=
UIColor
(
hex
:
0x599A0E
)
static
let
cityNoSelected
=
UIColor
(
hex
:
0xC5C5C5
)
.
withAlphaComponent
(
0.5
)
static
let
cityAddButtonBG
=
UIColor
(
hex
:
0x131315
)
static
let
searchBarTint
=
UIColor
(
hex
:
0xEBEBF5
)
.
withAlphaComponent
(
0.6
)
}
static
var
currentTheme
:
ThemeProtocol
{
...
...
1Weather/UI/Models/WdtLocation.swift
View file @
ce879c83
...
...
@@ -9,8 +9,6 @@
import
UIKit
class
WdtLocation
:
NSObject
,
NSCoding
{
static
let
LOCATION
=
"location"
static
let
CONDITIONS
=
"conditions"
static
let
DAYSUMMARIES
=
"daysummaries"
...
...
@@ -33,6 +31,27 @@ class WdtLocation: NSObject, NSCoding {
var
zip
:
String
?
fileprivate
var
_nickName
:
String
?
var
nickName
:
String
?
var
fullName
:
String
{
get
{
var
sb
=
String
()
if
city
?
.
count
??
0
>
0
{
sb
.
append
(
city
!
)
sb
.
append
(
", "
)
}
if
region
?
.
count
??
0
>
0
{
sb
.
append
(
region
!
)
sb
.
append
(
", "
)
}
if
country
?
.
count
??
0
>
0
{
sb
.
append
(
country
!
)
sb
.
append
(
", "
)
}
if
(
sb
.
count
>
0
)
{
sb
=
sb
.
trim
(
", "
)
// trim comma and space
}
return
sb
}
}
var
cityName
:
String
{
get
{
...
...
@@ -125,7 +144,6 @@ class WdtLocation: NSObject, NSCoding {
cityState
=
""
uvDesc
=
""
detailName
=
""
fullName
=
""
locationId
=
"us"
fileName
=
"us"
simpleFileName
=
"us"
...
...
@@ -139,7 +157,6 @@ class WdtLocation: NSObject, NSCoding {
cityState
=
""
uvDesc
=
""
detailName
=
""
fullName
=
""
locationId
=
"us"
fileName
=
"us"
simpleFileName
=
"us"
...
...
@@ -177,7 +194,6 @@ class WdtLocation: NSObject, NSCoding {
cityState
=
""
uvDesc
=
""
detailName
=
""
fullName
=
""
locationId
=
""
fileName
=
""
simpleFileName
=
""
...
...
@@ -242,8 +258,6 @@ class WdtLocation: NSObject, NSCoding {
var
detailName
:
String
var
fullName
:
String
var
isDay
:
Bool
=
false
...
...
1Weather/UI/Models/WeatherUpdateManager.swift
View file @
ce879c83
...
...
@@ -11,6 +11,33 @@ import UserNotifications
class
WeatherUpdateManager
:
NSObject
{
static
let
shared
=
WeatherUpdateManager
()
private
override
init
()
{
super
.
init
()
let
sf
=
WdtLocation
(
zip
:
"000001"
,
city
:
"San-Francisco"
,
region
:
"CA"
,
countryCode
:
"US"
,
country
:
"USA"
,
lat
:
"0"
,
lng
:
"0"
)
sf
.
currentConditions
=
WdtCondition
()
sf
.
currentConditions
?
.
tempC
=
"30"
sf
.
selectedLocation
=
true
let
seattle
=
WdtLocation
(
zip
:
"000002"
,
city
:
"Seattle"
,
region
:
"WA"
,
countryCode
:
"US"
,
country
:
"USA"
,
lat
:
"0"
,
lng
:
"0"
)
seattle
.
currentConditions
=
WdtCondition
()
seattle
.
currentConditions
?
.
tempC
=
"17"
seattle
.
selectedLocation
=
false
self
.
allWdtLocations
=
[
sf
,
seattle
]
}
var
allLocationsCount
:
Int
{
return
allWdtLocations
?
.
count
??
0
...
...
@@ -23,6 +50,16 @@ class WeatherUpdateManager: NSObject {
// Return true if it added as a new location, false if it didn't add it or it was a dup
func
addLocation
(
_
location
:
WdtLocation
)
->
Bool
{
print
(
"Add location
\(
location
)
"
)
allWdtLocations
?
.
forEach
{
$0
.
selectedLocation
=
false
}
if
let
index
=
(
allWdtLocations
?
.
firstIndex
{
$0
.
hash
==
location
.
hash
})
{
allWdtLocations
?[
index
]
.
selectedLocation
=
true
}
else
{
location
.
selectedLocation
=
true
allWdtLocations
?
.
append
(
location
)
}
return
true
}
...
...
@@ -30,6 +67,15 @@ class WeatherUpdateManager: NSObject {
// Return true if it added as a new location, false if it didn't add it or it was a dup
func
deleteLocation
(
_
location
:
WdtLocation
)
->
Bool
{
print
(
"Delete location
\(
location
)
"
)
if
let
locationToDeleteIndex
=
(
allWdtLocations
?
.
firstIndex
{
location
.
hash
==
$0
.
hash
})
{
allWdtLocations
?
.
remove
(
at
:
locationToDeleteIndex
)
if
location
.
selectedLocation
{
allWdtLocations
?
.
first
?
.
selectedLocation
=
true
}
}
return
true
}
...
...
1Weather/UI/View controllers/Location/Cells/CityCell.swift
View file @
ce879c83
...
...
@@ -10,6 +10,8 @@ import UIKit
class
CityCell
:
UITableViewCell
{
//Public
static
let
kIdentifier
=
"cityCell"
var
onSelect
:(()
->
Void
)?
var
onAdd
:(()
->
Void
)?
//Private
private
let
cityLabel
=
UILabel
()
...
...
@@ -27,20 +29,40 @@ class CityCell: UITableViewCell {
prepareTemperatureLabel
()
}
func
configure
(
geoName
:
GeoNamesPlace
,
mode
:
LocationsViewModelDisplayMode
)
{
cityLabel
.
text
=
geoName
.
city
addButton
.
isHidden
=
mode
==
.
savedCities
selectedButton
.
isHidden
=
mode
!=
.
savedCities
func
configure
(
wdtLocation
:
WdtLocation
,
mode
:
LocationsViewModelDisplayMode
)
{
cityLabel
.
text
=
wdtLocation
.
cityStateName
temperatureLabel
.
text
=
wdtLocation
.
currentConditions
?
.
temp
??
"--"
switch
mode
{
case
.
savedCities
:
addButton
.
isHidden
=
true
selectedButton
.
isHidden
=
false
UIView
.
performWithoutAnimation
{
self
.
selectedButton
.
tintColor
=
wdtLocation
.
selectedLocation
?
ThemeManager
.
Colors
.
citySelected
:
ThemeManager
.
Colors
.
cityNoSelected
}
case
.
popularCities
,
.
searchResults
:
addButton
.
isHidden
=
false
selectedButton
.
isHidden
=
true
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
@objc
private
func
handleAddButton
()
{
onAdd
?()
}
@objc
private
func
handleSelectButton
()
{
onSelect
?()
}
}
//MARK: Prepare
private
extension
CityCell
{
func
prepareCell
()
{
backgroundColor
=
ThemeManager
.
currentTheme
.
navigationBarBackgroundColor
contentView
.
backgroundColor
=
ThemeManager
.
currentTheme
.
navigationBarBackgroundColor
selectionStyle
=
.
none
}
...
...
@@ -50,7 +72,7 @@ private extension CityCell {
cityLabel
.
numberOfLines
=
1
cityLabel
.
lineBreakMode
=
.
byTruncatingTail
cityLabel
.
textColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
cityLabel
.
setContentHuggingPriority
(
.
init
(
10
00
),
for
:
.
horizontal
)
cityLabel
.
setContentHuggingPriority
(
.
init
(
9
00
),
for
:
.
horizontal
)
contentView
.
addSubview
(
cityLabel
)
cityLabel
.
snp
.
makeConstraints
{
(
make
)
in
...
...
@@ -70,6 +92,7 @@ private extension CityCell {
temperatureLabel
.
font
=
AppFont
.
SFPro
.
semibold
(
size
:
16
)
temperatureLabel
.
textColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
temperatureLabel
.
setContentHuggingPriority
(
.
init
(
1000
),
for
:
.
horizontal
)
temperatureLabel
.
setContentCompressionResistancePriority
(
.
init
(
1000
),
for
:
.
horizontal
)
container
.
addSubview
(
temperatureLabel
)
temperatureLabel
.
snp
.
makeConstraints
{
(
make
)
in
...
...
@@ -94,6 +117,7 @@ private extension CityCell {
addButton
.
setTitleColor
(
ThemeManager
.
Colors
.
locationBlue
,
for
:
.
normal
)
addButton
.
backgroundColor
=
ThemeManager
.
Colors
.
cityAddButtonBG
addButton
.
layer
.
cornerRadius
=
12
addButton
.
addTarget
(
self
,
action
:
#selector(
handleAddButton
)
,
for
:
.
touchUpInside
)
addButton
.
layer
.
shadowOffset
=
.
init
(
width
:
0
,
height
:
2
)
addButton
.
layer
.
shadowColor
=
UIColor
.
black
.
cgColor
...
...
@@ -115,6 +139,7 @@ private extension CityCell {
selectedButton
.
imageView
?
.
contentMode
=
.
scaleAspectFit
selectedButton
.
setImage
(
UIImage
(
named
:
"city_checkmark"
),
for
:
.
normal
)
selectedButton
.
tintColor
=
ThemeManager
.
Colors
.
cityNoSelected
selectedButton
.
addTarget
(
self
,
action
:
#selector(
handleAddButton
)
,
for
:
.
touchUpInside
)
contentView
.
addSubview
(
selectedButton
)
selectedButton
.
snp
.
makeConstraints
{
(
make
)
in
...
...
1Weather/UI/View controllers/Location/LocationViewController.swift
View file @
ce879c83
...
...
@@ -10,7 +10,7 @@ import UIKit
//MARK:- Location Navigation View Controller
class
LocationViewController
:
UINavigationController
{
init
()
{
let
savedCitiesViewController
=
Saved
CitiesViewController
()
let
savedCitiesViewController
=
CitiesViewController
()
super
.
init
(
rootViewController
:
savedCitiesViewController
)
}
...
...
@@ -31,23 +31,53 @@ class LocationViewController: UINavigationController {
}
}
private
class
SavedCitiesViewController
:
UIViewController
{
//MARK:- Cities View Controller
private
enum
EditButtonStyle
{
case
edit
case
done
}
private
class
CitiesViewController
:
UIViewController
{
//Private
private
let
searchBar
=
UISearchBar
()
private
let
locationButton
=
SelfSizingButton
(
frame
:
.
zero
)
private
let
tableView
=
UITableView
()
private
let
editButton
=
SelfSizingButton
()
private
let
locationsViewModel
=
LocationsViewModel
()
private
let
searchQueue
:
OperationQueue
=
{
let
queue
=
OperationQueue
()
queue
.
maxConcurrentOperationCount
=
1
return
queue
}()
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
super
.
viewDidLoad
()
view
.
backgroundColor
=
ThemeManager
.
currentTheme
.
navigationBarBackgroundColor
edgesForExtendedLayout
=
[]
self
.
locationsViewModel
.
delegate
=
self
prepareNavBar
()
prepareSearchBar
()
prepareLocationButton
()
prepareTableView
()
prepareEditButton
()
}
private
func
updateEditButton
(
style
:
EditButtonStyle
)
{
switch
style
{
case
.
edit
:
UIView
.
performWithoutAnimation
{
self
.
editButton
.
setImage
(
UIImage
(
named
:
"edit_pencil"
),
for
:
.
normal
)
self
.
editButton
.
setTitle
(
"EDIT"
.
localized
,
for
:
.
normal
)
}
case
.
done
:
UIView
.
performWithoutAnimation
{
self
.
editButton
.
setImage
(
nil
,
for
:
.
normal
)
self
.
editButton
.
setTitle
(
"DONE"
.
localized
,
for
:
.
normal
)
}
}
}
@objc
private
func
handleCloseButton
()
{
...
...
@@ -58,13 +88,14 @@ private class SavedCitiesViewController:UIViewController {
}
@objc
private
func
handleEditButton
()
{
@objc
private
func
handleEditButton
(
button
:
UIButton
)
{
tableView
.
setEditing
(
!
tableView
.
isEditing
,
animated
:
true
)
self
.
updateEditButton
(
style
:
tableView
.
isEditing
?
.
done
:
.
edit
)
}
}
//MARK:- Saved cities prepare
private
extension
Saved
CitiesViewController
{
private
extension
CitiesViewController
{
func
prepareNavBar
()
{
self
.
navigationController
?
.
view
.
backgroundColor
=
.
white
...
...
@@ -93,8 +124,12 @@ private extension SavedCitiesViewController {
}
func
prepareSearchBar
()
{
let
searchBarTextField
=
searchBar
.
value
(
forKey
:
"searchField"
)
as?
UITextField
searchBarTextField
?
.
textColor
=
ThemeManager
.
currentTheme
.
navigationTintColor
searchBarTextField
?
.
leftView
?
.
tintColor
=
ThemeManager
.
Colors
.
searchBarTint
searchBar
.
searchBarStyle
=
.
minimal
searchBar
.
placeholder
=
"Search"
.
localized
(
comment
:
"Search bar placeholder text."
)
searchBar
.
delegate
=
self
view
.
addSubview
(
searchBar
)
searchBar
.
snp
.
makeConstraints
{
(
make
)
in
make
.
top
.
equalToSuperview
()
...
...
@@ -106,7 +141,7 @@ private extension SavedCitiesViewController {
func
prepareLocationButton
()
{
locationButton
.
tintColor
=
ThemeManager
.
Colors
.
locationBlue
locationButton
.
setImage
(
UIImage
(
named
:
"location_arrow"
),
for
:
.
normal
)
locationButton
.
setTitle
(
"Use Current Location"
,
for
:
.
normal
)
locationButton
.
setTitle
(
"Use Current Location"
.
localized
,
for
:
.
normal
)
locationButton
.
setTitleColor
(
ThemeManager
.
Colors
.
locationBlue
,
for
:
.
normal
)
locationButton
.
setTitleColor
(
ThemeManager
.
Colors
.
locationBlue
.
highlighted
,
for
:
.
highlighted
)
locationButton
.
addTarget
(
self
,
action
:
#selector(
handleLocationButton
)
,
for
:
.
touchUpInside
)
...
...
@@ -122,7 +157,6 @@ private extension SavedCitiesViewController {
}
func
prepareTableView
()
{
let
tableView
=
UITableView
()
tableView
.
backgroundColor
=
view
.
backgroundColor
tableView
.
register
(
CityCell
.
self
,
forCellReuseIdentifier
:
CityCell
.
kIdentifier
)
tableView
.
tableFooterView
=
UIView
()
...
...
@@ -138,50 +172,87 @@ private extension SavedCitiesViewController {
make
.
bottom
.
equalToSuperview
()
}
}
func
prepareEditButton
()
{
editButton
.
setImage
(
UIImage
(
named
:
"edit_pencil"
),
for
:
.
normal
)
editButton
.
tintColor
=
ThemeManager
.
Colors
.
locationBlue
editButton
.
setTitle
(
"EDIT"
.
localized
,
for
:
.
normal
)
editButton
.
setTitleColor
(
ThemeManager
.
Colors
.
locationBlue
.
highlighted
,
for
:
.
highlighted
)
editButton
.
setTitleColor
(
ThemeManager
.
Colors
.
locationBlue
,
for
:
.
normal
)
editButton
.
titleLabel
?
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
12
)
editButton
.
titleEdgeInsets
=
.
init
(
top
:
0
,
left
:
6
,
bottom
:
0
,
right
:
0
)
editButton
.
addTarget
(
self
,
action
:
#selector(
handleEditButton(button:)
)
,
for
:
.
touchUpInside
)
}
}
//MARK:- LocationsViewModel Delegate
extension
CitiesViewController
:
LocationsViewModelDelegate
{
func
viewModelDidChange
(
model
:
LocationsViewModel
)
{
DispatchQueue
.
main
.
async
{
self
.
tableView
.
reloadData
()
}
}
func
viewModelDisplayModeDidChange
(
model
:
LocationsViewModel
)
{
DispatchQueue
.
main
.
async
{
self
.
tableView
.
reloadData
()
}
}
func
viewModel
(
model
:
LocationsViewModel
,
errorHasOccured
error
:
String
?)
{
self
.
showAlert
(
withTitle
:
"Error"
,
message
:
error
)
}
}
//MARK: UItableView Data Source
extension
Saved
CitiesViewController
:
UITableViewDataSource
{
extension
CitiesViewController
:
UITableViewDataSource
{
func
tableView
(
_
tableView
:
UITableView
,
numberOfRowsInSection
section
:
Int
)
->
Int
{
return
locationsViewModel
.
cities
.
count
}
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
)
->
UITableViewCell
{
let
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
CityCell
.
kIdentifier
,
for
:
indexPath
)
as!
CityCell
cell
.
configure
(
geoName
:
locationsViewModel
.
cities
[
indexPath
.
row
],
cell
.
configure
(
wdtLocation
:
locationsViewModel
.
cities
[
indexPath
.
row
],
mode
:
locationsViewModel
.
displayMode
)
cell
.
onAdd
=
{
[
weak
self
]
in
guard
let
strongSelf
=
self
else
{
return
}
strongSelf
.
locationsViewModel
.
add
(
city
:
strongSelf
.
locationsViewModel
.
cities
[
indexPath
.
row
])
}
cell
.
onSelect
=
{[
weak
self
]
in
guard
let
strongSelf
=
self
else
{
return
}
strongSelf
.
locationsViewModel
.
select
(
city
:
strongSelf
.
locationsViewModel
.
cities
[
indexPath
.
row
])
}
return
cell
}
}
//MARK: UITableView Delegate
extension
Saved
CitiesViewController
:
UITableViewDelegate
{
extension
CitiesViewController
:
UITableViewDelegate
{
func
tableView
(
_
tableView
:
UITableView
,
viewForHeaderInSection
section
:
Int
)
->
UIView
?
{
let
container
=
UIView
()
container
.
backgroundColor
=
ThemeManager
.
currentTheme
.
navigationBarBackgroundColor
let
titleLabel
=
UILabel
()
titleLabel
.
text
=
"Saved Cities"
.
localized
+
"(
\(
self
.
locationsViewModel
.
cities
.
count
)
)"
titleLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
24
)
titleLabel
.
textColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
container
.
addSubview
(
titleLabel
)
if
locationsViewModel
.
displayMode
==
.
savedCities
{
let
editButton
=
SelfSizingButton
()
editButton
.
setImage
(
UIImage
(
named
:
"edit_pencil"
),
for
:
.
normal
)
editButton
.
tintColor
=
ThemeManager
.
Colors
.
locationBlue
editButton
.
setTitle
(
"EDIT"
,
for
:
.
normal
)
editButton
.
setTitleColor
(
ThemeManager
.
Colors
.
locationBlue
.
highlighted
,
for
:
.
highlighted
)
editButton
.
setTitleColor
(
ThemeManager
.
Colors
.
locationBlue
,
for
:
.
normal
)
editButton
.
titleLabel
?
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
12
)
editButton
.
titleEdgeInsets
=
.
init
(
top
:
0
,
left
:
6
,
bottom
:
0
,
right
:
0
)
editButton
.
addTarget
(
self
,
action
:
#selector(
handleEditButton
)
,
for
:
.
touchUpInside
)
switch
self
.
locationsViewModel
.
displayMode
{
case
.
savedCities
:
titleLabel
.
text
=
"Saved Cities"
.
localized
+
"(
\(
self
.
locationsViewModel
.
cities
.
count
)
)"
//Add Edit button
container
.
addSubview
(
editButton
)
editButton
.
snp
.
makeConstraints
{
(
make
)
in
make
.
right
.
equalToSuperview
()
.
inset
(
24
)
make
.
bottom
.
equalTo
(
titleLabel
)
}
case
.
popularCities
:
titleLabel
.
text
=
"5 Popular cities"
.
localized
case
.
searchResults
:
titleLabel
.
text
=
"Results"
.
localized
+
"(
\(
self
.
locationsViewModel
.
cities
.
count
)
)"
}
titleLabel
.
snp
.
makeConstraints
{
(
make
)
in
...
...
@@ -192,4 +263,66 @@ extension SavedCitiesViewController: UITableViewDelegate {
return
container
}
func
tableView
(
_
tableView
:
UITableView
,
willBeginEditingRowAt
indexPath
:
IndexPath
)
{
print
(
"Will begin editing"
)
self
.
updateEditButton
(
style
:
.
done
)
}
func
tableView
(
_
tableView
:
UITableView
,
didEndEditingRowAt
indexPath
:
IndexPath
?)
{
print
(
"Did end editing"
)
self
.
updateEditButton
(
style
:
.
edit
)
}
func
tableView
(
_
tableView
:
UITableView
,
commit
editingStyle
:
UITableViewCell
.
EditingStyle
,
forRowAt
indexPath
:
IndexPath
)
{
let
cityToDelete
=
self
.
locationsViewModel
.
cities
[
indexPath
.
row
]
self
.
locationsViewModel
.
delete
(
city
:
cityToDelete
)
}
}
//MARK:- UISearchBar Delegate
extension
CitiesViewController
:
UISearchBarDelegate
{
func
searchBarTextDidBeginEditing
(
_
searchBar
:
UISearchBar
)
{
searchBar
.
setShowsCancelButton
(
true
,
animated
:
true
)
self
.
locationsViewModel
.
displayMode
=
.
popularCities
self
.
locationsViewModel
.
fetchPopularCities
()
}
func
searchBar
(
_
searchBar
:
UISearchBar
,
textDidChange
searchText
:
String
)
{
defer
{
self
.
locationsViewModel
.
displayMode
=
.
searchResults
}
if
searchText
.
count
==
0
{
self
.
locationsViewModel
.
clean
()
return
}
searchQueue
.
cancelAllOperations
()
let
operation
=
BlockOperation
()
weak
var
weakOperation
=
operation
operation
.
addExecutionBlock
{
[
weak
self
]
in
Thread
.
sleep
(
forTimeInterval
:
0.5
)
guard
weakOperation
?
.
isCancelled
==
false
else
{
return
}
self
?
.
locationsViewModel
.
fetchCities
(
query
:
searchText
)
}
searchQueue
.
addOperation
(
operation
)
}
func
searchBarCancelButtonClicked
(
_
searchBar
:
UISearchBar
)
{
searchBar
.
setShowsCancelButton
(
false
,
animated
:
true
)
self
.
searchBar
.
endEditing
(
true
)
searchBar
.
text
=
nil
self
.
locationsViewModel
.
displayMode
=
.
savedCities
}
func
searchBarSearchButtonClicked
(
_
searchBar
:
UISearchBar
)
{
searchBar
.
setShowsCancelButton
(
false
,
animated
:
true
)
self
.
searchBar
.
endEditing
(
true
)
}
}
1Weather/UI/View controllers/Location/LocationsViewModel.swift
View file @
ce879c83
...
...
@@ -11,55 +11,74 @@ import AlgoliaSearchClient
protocol
LocationsViewModelDelegate
:
class
{
func
viewModelDidChange
(
model
:
LocationsViewModel
)
func
viewModelDisplayModeDidChange
(
model
:
LocationsViewModel
)
func
viewModel
(
model
:
LocationsViewModel
,
errorHasOccured
error
:
Error
)
func
viewModel
(
model
:
LocationsViewModel
,
errorHasOccured
error
:
String
?
)
}
enum
LocationsViewModelDisplayMode
{
case
savedCities
case
popularCities
case
searchResult
case
searchResult
s
}
class
LocationsViewModel
{
//Public
weak
var
delegate
:
LocationsViewModelDelegate
?
private(set)
var
cities
=
[
GeoNamesPlace
]()
{
var
cities
:[
WdtLocation
]
{
switch
self
.
displayMode
{
case
.
savedCities
:
return
WeatherUpdateManager
.
shared
.
allWdtLocations
??
[
WdtLocation
]()
case
.
popularCities
:
return
self
.
popularCities
case
.
searchResults
:
return
self
.
fetchedCities
}
}
var
displayMode
:
LocationsViewModelDisplayMode
=
.
savedCities
{
didSet
{
if
oldValue
==
.
searchResults
{
clean
()
}
self
.
delegate
?
.
viewModelDisplayModeDidChange
(
model
:
self
)
}
}
//Private
private
let
popularCitiesManager
=
PopularCitiesManager
()
private
var
popularCities
=
[
WdtLocation
]()
{
didSet
{
assert
(
Thread
.
isMainThread
)
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
}
private(set)
var
displayMode
:
LocationsViewModelDisplayMode
=
.
savedCities
init
()
{
testGeo
()
private
var
fetchedCities
=
[
WdtLocation
]()
{
didSet
{
assert
(
Thread
.
isMainThread
)
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
}
private
func
testGeo
()
{
let
perm
=
GeoNamesPlace
()
perm
.
city
=
"Perm asfaskdf aslojkraijasijaowierhopaiwr"
perm
.
stateCode
=
"614000"
perm
.
country
=
"Russia"
let
moscow
=
GeoNamesPlace
()
moscow
.
city
=
"Moscow"
moscow
.
stateCode
=
"000000"
moscow
.
country
=
"Russia"
//MARK:- ViewModel life cycle
func
clean
()
{
fetchedCities
.
removeAll
()
}
let
sp
=
GeoNamesPlace
()
sp
.
city
=
"Saint-Petersburg"
sp
.
stateCode
=
"000000"
sp
.
country
=
"Russia"
func
fetchPopularCities
()
{
self
.
popularCitiesManager
.
fetchPopularCities
{[
weak
self
]
result
in
guard
let
strongSelf
=
self
else
{
return
}
let
kazan
=
GeoNamesPlace
()
kazan
.
city
=
"Kazan"
kazan
.
stateCode
=
"000000"
kazan
.
country
=
"Russia"
cities
=
[
perm
,
moscow
,
sp
,
kazan
]
switch
result
{
case
.
success
(
let
popularCities
):
DispatchQueue
.
main
.
async
{
strongSelf
.
popularCities
=
popularCities
.
map
{
return
WdtLocation
(
place
:
$0
)}
}
case
.
failure
(
let
error
):
strongSelf
.
delegate
?
.
viewModel
(
model
:
strongSelf
,
errorHasOccured
:
error
.
localizedDescription
)
}
}
}
func
fetchCities
(
query
:
String
)
{
// This is a test location that can be interpreted on the server to return all alerts
guard
query
!=
"1wville"
else
{
let
fakePlace
=
GeoNamesPlace
()
...
...
@@ -74,7 +93,7 @@ class LocationsViewModel {
fakePlace
.
toponymName
=
"1WVille"
DispatchQueue
.
main
.
async
{
self
.
c
ities
=
[]
self
.
fetchedC
ities
=
[]
}
return
}
...
...
@@ -90,7 +109,9 @@ class LocationsViewModel {
var
filteredPlaces
=
[
GeoNamesPlace
]()
placesClient
.
search
(
query
:
algoliaQuery
,
language
:
language
,
requestOptions
:
nil
)
{
(
result
:
Result
<
PlacesClient
.
SingleLanguageResponse
,
Error
>
)
in
placesClient
.
search
(
query
:
algoliaQuery
,
language
:
language
,
requestOptions
:
nil
)
{[
weak
self
]
(
result
:
Result
<
PlacesClient
.
SingleLanguageResponse
,
Error
>
)
in
guard
let
strongSelf
=
self
else
{
return
}
switch
(
result
)
{
case
.
success
(
let
response
):
print
(
"Search: got
\(
response
.
nbHits
)
results"
)
...
...
@@ -117,30 +138,51 @@ class LocationsViewModel {
filteredPlaces
.
append
(
place
)
}
DispatchQueue
.
main
.
async
{
s
elf
.
cities
=
filteredPlaces
s
trongSelf
.
fetchedCities
=
filteredPlaces
.
map
{
return
WdtLocation
(
place
:
$0
)}
}
break
case
.
failure
(
let
error
):
DispatchQueue
.
main
.
async
{
s
elf
.
delegate
?
.
viewModel
(
model
:
self
,
errorHasOccured
:
error
)
s
trongSelf
.
delegate
?
.
viewModel
(
model
:
strongSelf
,
errorHasOccured
:
error
.
localizedDescription
)
}
break
}
}
}
func
add
(
city
:
GeoNamesPlace
)
{
//MARK:- City CUD methods
func
add
(
city
:
WdtLocation
)
{
// TODO: Just update self.cities, it will trigger a viewModelDidChange call
// let newCity = WdtLocation(zip: nil, city: "New City", region: "NS", countryCode: "US", country: "USA", lat: nil, lng: nil)
if
WeatherUpdateManager
.
shared
.
addLocation
(
city
)
{
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
else
{
self
.
delegate
?
.
viewModel
(
model
:
self
,
errorHasOccured
:
"Failed to add location"
)
}
}
func
delete
(
city
:
GeoNamesPlace
)
{
func
delete
(
city
:
WdtLocation
)
{
// TODO: Just update self.cities, it will trigger a viewModelDidChange call
if
WeatherUpdateManager
.
shared
.
deleteLocation
(
city
)
{
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
else
{
self
.
delegate
?
.
viewModel
(
model
:
self
,
errorHasOccured
:
"Failed to delete location"
)
}
}
func
select
(
city
:
GeoNamesPlace
)
{
func
select
(
city
:
WdtLocation
)
{
// TODO: Tell delegate to refresh UI
if
WeatherUpdateManager
.
shared
.
addLocation
(
city
)
{
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
else
{
self
.
delegate
?
.
viewModel
(
model
:
self
,
errorHasOccured
:
"Failed to add location"
)
}
}
}
1weather_IOS.sketch
View file @
ce879c83
No preview for this file type
Pods/Pods.xcodeproj/project.pbxproj
View file @
ce879c83
...
...
@@ -466,7 +466,7 @@
438C6B748266BEE80EA0A61421AB1DC5
/* Transport.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
Transport.swift
;
path
=
Sources/AlgoliaSearchClient/Transport/Common/Transport.swift
;
sourceTree
=
"<group>"
;
};
43CA5B2AE7B71A765DBF6E7CE8FD0380
/* Hit.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
Hit.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Search/Hit/Hit.swift
;
sourceTree
=
"<group>"
;
};
43F37669F1A1D739503181E11E936241
/* AnyWaitable.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
AnyWaitable.swift
;
path
=
Sources/AlgoliaSearchClient/Helpers/Wait/AnyWaitable.swift
;
sourceTree
=
"<group>"
;
};
4418FB4E800DFA4DB13A6252DCF8A266
/* Pods_1Weather.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
name
=
Pods_1Weather.framework
;
path
=
"Pods-1Weather.framework"
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
4418FB4E800DFA4DB13A6252DCF8A266
/* Pods_1Weather.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
path
=
Pods_1Weather.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
44314B3A082956F6E67EAAEBEDF20203
/* AsyncOperation.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
AsyncOperation.swift
;
path
=
Sources/AlgoliaSearchClient/Async/AsyncOperation.swift
;
sourceTree
=
"<group>"
;
};
4451CAD26B82503E6C6A9F73392D0259
/* PathComponent.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
PathComponent.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Internal/Path/PathComponent.swift
;
sourceTree
=
"<group>"
;
};
4717C4D256C32A29F1E5544304FAFF0F
/* LayoutConstraintItem.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
LayoutConstraintItem.swift
;
path
=
Source/LayoutConstraintItem.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -559,7 +559,7 @@
895B3A8A73AEB00123729C2E1C6138B6
/* TaggedString.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
TaggedString.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Search/Response/SearchResponse/Auxiliary/Highlighting/TaggedString.swift
;
sourceTree
=
"<group>"
;
};
89FAA39CC1F46DECB0200EBD443BDCDE
/* Cursor.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
Cursor.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Search/Indexing/Cursor.swift
;
sourceTree
=
"<group>"
;
};
8B363907CD28FB366DF6B8CB60A29DB1
/* FacetStats.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
FacetStats.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Search/Response/SearchResponse/Auxiliary/FacetStats/FacetStats.swift
;
sourceTree
=
"<group>"
;
};
8BC89BBA07ABC039D176A0220D50F6E2
/* AlgoliaSearchClient.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
name
=
AlgoliaSearchClient.framework
;
path
=
AlgoliaSearchClient.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
8BC89BBA07ABC039D176A0220D50F6E2
/* AlgoliaSearchClient.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
path
=
AlgoliaSearchClient.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
8CA8B75533EC930206B9AC674A8680DB
/* ClientDateCodingStrategy.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
ClientDateCodingStrategy.swift
;
path
=
Sources/AlgoliaSearchClient/Helpers/Coding/Date/ClientDateCodingStrategy.swift
;
sourceTree
=
"<group>"
;
};
8D9F168995CEEE7755D8FFCAF33E1197
/* Path.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
Path.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Internal/Path/Path.swift
;
sourceTree
=
"<group>"
;
};
8DE07A549CBA73BA74BFD3C4554FD15F
/* BoolContainer.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
BoolContainer.swift
;
path
=
Sources/AlgoliaSearchClient/Helpers/Coding/Wrappers/BoolContainer.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -572,14 +572,14 @@
95583237E77B7F62739559AD33396C0A
/* Logging.release.xcconfig */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
text.xcconfig
;
path
=
Logging.release.xcconfig
;
sourceTree
=
"<group>"
;
};
9730EC6BB0C718FBA03EE62D0C832E89
/* AlgoliaSearchClient-Info.plist */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
text.plist.xml
;
path
=
"AlgoliaSearchClient-Info.plist"
;
sourceTree
=
"<group>"
;
};
97859DC2CD452FEA47EF1A5B35E75B14
/* TimeRange.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
TimeRange.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Common/TimeRange.swift
;
sourceTree
=
"<group>"
;
};
979486118B3E90C08386079D57962701
/* SnapKit.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
name
=
SnapKit.framework
;
path
=
SnapKit.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
979486118B3E90C08386079D57962701
/* SnapKit.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
path
=
SnapKit.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
97978974EBDA3629FAF8F7B484D2CBF6
/* TransportContainer.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
TransportContainer.swift
;
path
=
Sources/AlgoliaSearchClient/Transport/Common/TransportContainer.swift
;
sourceTree
=
"<group>"
;
};
97E32C02BFE41CA9E5DB175D8ED61483
/* Transport+CustomRequest.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
"Transport+CustomRequest.swift"
;
path
=
"Sources/AlgoliaSearchClient/Transport/Common/Transport+CustomRequest.swift"
;
sourceTree
=
"<group>"
;
};
9BB2FCF94697E5CC72393A20418CB467
/* ConstraintLayoutGuideDSL.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
ConstraintLayoutGuideDSL.swift
;
path
=
Source/ConstraintLayoutGuideDSL.swift
;
sourceTree
=
"<group>"
;
};
9BF5BCCDB63902AD39DAEC7EBBFB7B86
/* ConstraintOffsetTarget.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
ConstraintOffsetTarget.swift
;
path
=
Source/ConstraintOffsetTarget.swift
;
sourceTree
=
"<group>"
;
};
9C27A6306CED6A52F9F42197B318913D
/* SearchClient+APIKey.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
"SearchClient+APIKey.swift"
;
path
=
"Sources/AlgoliaSearchClient/Client/Search/SearchClient+APIKey.swift"
;
sourceTree
=
"<group>"
;
};
9D0BCAC1D7172B5D44F0E1B5DE690E2C
/* MatchLevel.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
MatchLevel.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Search/Hit/MatchLevel.swift
;
sourceTree
=
"<group>"
;
};
9D940727FF8FB9C785EB98E56350EF41
/* Podfile */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
text.script.ruby
;
includeInIndex
=
1
;
indentWidth
=
2
;
lastKnownFileType
=
text
;
name
=
Podfile
;
path
=
../Podfile
;
sourceTree
=
SOURCE_ROOT
;
tabWidth
=
2
;
xcLanguageSpecificationIdentifier
=
xcode.lang.ruby
;
};
9D940727FF8FB9C785EB98E56350EF41
/* Podfile */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
text.script.ruby
;
includeInIndex
=
1
;
indentWidth
=
2
;
name
=
Podfile
;
path
=
../Podfile
;
sourceTree
=
SOURCE_ROOT
;
tabWidth
=
2
;
xcLanguageSpecificationIdentifier
=
xcode.lang.ruby
;
};
9EF3C6A7EBDCBDF83BBA52FD4CDD03D7
/* AnalyticsClient.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
AnalyticsClient.swift
;
path
=
Sources/AlgoliaSearchClient/Client/AnalyticsClient.swift
;
sourceTree
=
"<group>"
;
};
9F6FEA6785E4A746B66D36B6C6929316
/* TopUserIDResponse.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
TopUserIDResponse.swift
;
path
=
Sources/AlgoliaSearchClient/Models/MultiCluster/TopUserIDResponse.swift
;
sourceTree
=
"<group>"
;
};
A0408627B86CC1DCD7AB5ED6425A49C0
/* SearchClient+MultiCluster.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
"SearchClient+MultiCluster.swift"
;
path
=
"Sources/AlgoliaSearchClient/Client/Search/SearchClient+MultiCluster.swift"
;
sourceTree
=
"<group>"
;
};
...
...
@@ -591,7 +591,7 @@
A32B6EC0910F6D16360EB7B128939375
/* Pods-1Weather-dummy.m */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.c.objc
;
path
=
"Pods-1Weather-dummy.m"
;
sourceTree
=
"<group>"
;
};
A32E9E68F3B2F8221A461CFF3CAC9C20
/* SearchClient+Logs.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
"SearchClient+Logs.swift"
;
path
=
"Sources/AlgoliaSearchClient/Client/Search/SearchClient+Logs.swift"
;
sourceTree
=
"<group>"
;
};
A6103C61FDB009CBF30062E07BEA8E15
/* RecommendationClient.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
RecommendationClient.swift
;
path
=
Sources/AlgoliaSearchClient/Client/RecommendationClient.swift
;
sourceTree
=
"<group>"
;
};
A6513E0A6CB60623515716E73996F0F5
/* Logging.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
name
=
Logging.framework
;
path
=
Logging.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
A6513E0A6CB60623515716E73996F0F5
/* Logging.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
includeInIndex
=
0
;
path
=
Logging.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
A665BA0A5E49A37993662ABFFFE2FEB7
/* FacetsStorage.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
FacetsStorage.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Search/Response/SearchResponse/Auxiliary/Facet/FacetsStorage.swift
;
sourceTree
=
"<group>"
;
};
A73BB1CDB727E0EC318F4E61DB9A8BA5
/* AlgoliaSearchClient-dummy.m */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.c.objc
;
path
=
"AlgoliaSearchClient-dummy.m"
;
sourceTree
=
"<group>"
;
};
A7F13D1A2767DC6B7667EA21883DEF3A
/* QueryID.swift */
=
{
isa
=
PBXFileReference
;
includeInIndex
=
1
;
lastKnownFileType
=
sourcecode.swift
;
name
=
QueryID.swift
;
path
=
Sources/AlgoliaSearchClient/Models/Search/Query/QueryID.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -810,7 +810,6 @@
F72317B4D957B3956CEA8C47AECB20FD
/* UILayoutSupport+Extensions.swift */
,
53AE55659433C8AD57D5E71785FC5C94
/* Support Files */
,
);
name
=
SnapKit
;
path
=
SnapKit
;
sourceTree
=
"<group>"
;
};
...
...
@@ -837,7 +836,6 @@
AD64B0F1C0ABD2D396AC70142B7F0B95
/* LogHandler.swift */
,
8D67773DDB44F1F8B287710200467BA7
/* Support Files */
,
);
name
=
Logging
;
path
=
Logging
;
sourceTree
=
"<group>"
;
};
...
...
@@ -1160,7 +1158,6 @@
394D4D791D983A66A90DF27CF3BC36CB
/* WaitTask.swift */
,
45473BBE74E1139386E8AF33A22B9A54
/* Support Files */
,
);
name
=
AlgoliaSearchClient
;
path
=
AlgoliaSearchClient
;
sourceTree
=
"<group>"
;
};
...
...
@@ -1333,7 +1330,7 @@
isa
=
PBXProject
;
attributes
=
{
LastSwiftUpdateCheck
=
1100
;
LastUpgradeCheck
=
1
10
0
;
LastUpgradeCheck
=
1
22
0
;
};
buildConfigurationList
=
4821239608C13582E20E6DA73FD5F1F9
/* Build configuration list for PBXProject "Pods" */
;
compatibilityVersion
=
"Xcode 10.0"
;
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/AlgoliaSearchClient.xcscheme
View file @
ce879c83
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion =
"1
10
0"
LastUpgradeVersion =
"1
22
0"
version =
"1.3"
>
<BuildAction
parallelizeBuildables =
"YES"
buildImplicitDependencies =
"YES"
>
<BuildActionEntries>
<BuildActionEntry
buildForAnalyzing =
"YES"
buildForTesting =
"YES"
buildForRunning =
"YES"
buildForProfiling =
"YES"
buildForArchiving =
"YES"
>
buildForArchiving =
"YES"
buildForAnalyzing =
"YES"
>
<BuildableReference
BuildableIdentifier =
"primary"
BlueprintIdentifier =
"501CD213CC527E89056B36384FE73683"
...
...
@@ -23,14 +23,15 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration =
"Debug"
selectedDebuggerIdentifier =
"Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier =
"Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv =
"YES"
buildConfiguration =
"Debug"
>
<AdditionalOptions>
</AdditionalOptions>
shouldUseLaunchSchemeArgsEnv =
"YES"
>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration =
"Debug"
selectedDebuggerIdentifier =
"Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier =
"Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle =
"0"
...
...
@@ -38,17 +39,14 @@
ignoresPersistentStateOnLaunch =
"NO"
debugDocumentVersioning =
"YES"
debugServiceExtension =
"internal"
buildConfiguration =
"Debug"
allowLocationSimulation =
"YES"
>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration =
"Release"
shouldUseLaunchSchemeArgsEnv =
"YES"
savedToolIdentifier =
""
useCustomWorkingDirectory =
"NO"
debugDocumentVersioning =
"YES"
buildConfiguration =
"Release"
shouldUseLaunchSchemeArgsEnv =
"YES"
>
debugDocumentVersioning =
"YES"
>
</ProfileAction>
<AnalyzeAction
buildConfiguration =
"Debug"
>
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/Logging.xcscheme
View file @
ce879c83
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion =
"1
10
0"
LastUpgradeVersion =
"1
22
0"
version =
"1.3"
>
<BuildAction
parallelizeBuildables =
"YES"
buildImplicitDependencies =
"YES"
>
<BuildActionEntries>
<BuildActionEntry
buildForAnalyzing =
"YES"
buildForTesting =
"YES"
buildForRunning =
"YES"
buildForProfiling =
"YES"
buildForArchiving =
"YES"
>
buildForArchiving =
"YES"
buildForAnalyzing =
"YES"
>
<BuildableReference
BuildableIdentifier =
"primary"
BlueprintIdentifier =
"2ABF3F8EC6CE525E1E02C51D72C64E94"
...
...
@@ -23,14 +23,15 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration =
"Debug"
selectedDebuggerIdentifier =
"Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier =
"Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv =
"YES"
buildConfiguration =
"Debug"
>
<AdditionalOptions>
</AdditionalOptions>
shouldUseLaunchSchemeArgsEnv =
"YES"
>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration =
"Debug"
selectedDebuggerIdentifier =
"Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier =
"Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle =
"0"
...
...
@@ -38,17 +39,14 @@
ignoresPersistentStateOnLaunch =
"NO"
debugDocumentVersioning =
"YES"
debugServiceExtension =
"internal"
buildConfiguration =
"Debug"
allowLocationSimulation =
"YES"
>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration =
"Release"
shouldUseLaunchSchemeArgsEnv =
"YES"
savedToolIdentifier =
""
useCustomWorkingDirectory =
"NO"
debugDocumentVersioning =
"YES"
buildConfiguration =
"Release"
shouldUseLaunchSchemeArgsEnv =
"YES"
>
debugDocumentVersioning =
"YES"
>
</ProfileAction>
<AnalyzeAction
buildConfiguration =
"Debug"
>
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/Pods-1Weather.xcscheme
View file @
ce879c83
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion =
"1
10
0"
LastUpgradeVersion =
"1
22
0"
version =
"1.3"
>
<BuildAction
parallelizeBuildables =
"YES"
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/SnapKit.xcscheme
View file @
ce879c83
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion =
"1
10
0"
LastUpgradeVersion =
"1
22
0"
version =
"1.3"
>
<BuildAction
parallelizeBuildables =
"YES"
buildImplicitDependencies =
"YES"
>
<BuildActionEntries>
<BuildActionEntry
buildForAnalyzing =
"YES"
buildForTesting =
"YES"
buildForRunning =
"YES"
buildForProfiling =
"YES"
buildForArchiving =
"YES"
>
buildForArchiving =
"YES"
buildForAnalyzing =
"YES"
>
<BuildableReference
BuildableIdentifier =
"primary"
BlueprintIdentifier =
"19622742EBA51E823D6DAE3F8CDBFAD4"
...
...
@@ -23,14 +23,15 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration =
"Debug"
selectedDebuggerIdentifier =
"Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier =
"Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv =
"YES"
buildConfiguration =
"Debug"
>
<AdditionalOptions>
</AdditionalOptions>
shouldUseLaunchSchemeArgsEnv =
"YES"
>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration =
"Debug"
selectedDebuggerIdentifier =
"Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier =
"Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle =
"0"
...
...
@@ -38,17 +39,14 @@
ignoresPersistentStateOnLaunch =
"NO"
debugDocumentVersioning =
"YES"
debugServiceExtension =
"internal"
buildConfiguration =
"Debug"
allowLocationSimulation =
"YES"
>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration =
"Release"
shouldUseLaunchSchemeArgsEnv =
"YES"
savedToolIdentifier =
""
useCustomWorkingDirectory =
"NO"
debugDocumentVersioning =
"YES"
buildConfiguration =
"Release"
shouldUseLaunchSchemeArgsEnv =
"YES"
>
debugDocumentVersioning =
"YES"
>
</ProfileAction>
<AnalyzeAction
buildConfiguration =
"Debug"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment