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
5d1529f8
Commit
5d1529f8
authored
Mar 04, 2021
by
Demid Merzlyakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working network request parsing.
parent
f77af241
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
103 additions
and
160 deletions
+103
-160
1Weather/AppDelegate.swift
+3
-0
1Weather/Coordinators/TodayCoordinator.swift
+1
-1
1Weather/Model/LocationManager.swift
+35
-6
1Weather/Model/ModelObjects/Location.swift
+2
-15
1Weather/Network/Model/HelperObjects/WdtWeatherCode.swift
+0
-2
1Weather/Network/Model/WdtDailySummary.swift
+3
-3
1Weather/Network/Model/WdtHourlySummary.swift
+3
-3
1Weather/Network/Model/WdtLocation.swift
+11
-1
1Weather/Network/Model/WdtSurfaceObservation.swift
+3
-10
1Weather/Network/WdtWeatherSource.swift
+9
-25
1Weather/UI/View controllers/Today/TodayViewController.swift
+9
-0
1Weather/ViewModels/TodayViewModel.swift
+24
-94
No files found.
1Weather/AppDelegate.swift
View file @
5d1529f8
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
//
//
import
UIKit
import
UIKit
import
CoreLocation
@main
@main
class
AppDelegate
:
UIResponder
,
UIApplicationDelegate
{
class
AppDelegate
:
UIResponder
,
UIApplicationDelegate
{
...
@@ -14,6 +15,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
...
@@ -14,6 +15,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func
application
(
_
application
:
UIApplication
,
didFinishLaunchingWithOptions
launchOptions
:
[
UIApplication
.
LaunchOptionsKey
:
Any
]?)
->
Bool
{
func
application
(
_
application
:
UIApplication
,
didFinishLaunchingWithOptions
launchOptions
:
[
UIApplication
.
LaunchOptionsKey
:
Any
]?)
->
Bool
{
ThemeManager
.
refreshAppearance
()
ThemeManager
.
refreshAppearance
()
LocationManager
.
shared
.
currentLocation
=
Location
(
coordinates
:
CLLocationCoordinate2D
(
latitude
:
40.730610
,
longitude
:
-
73.935242
),
timeZone
:
TimeZone
(
identifier
:
"EST"
)
!
)
self
.
window
=
UIWindow
(
frame
:
UIScreen
.
main
.
bounds
)
self
.
window
=
UIWindow
(
frame
:
UIScreen
.
main
.
bounds
)
let
appCoordinator
=
AppCoordinator
(
window
:
self
.
window
!
)
let
appCoordinator
=
AppCoordinator
(
window
:
self
.
window
!
)
...
...
1Weather/Coordinators/TodayCoordinator.swift
View file @
5d1529f8
...
@@ -9,7 +9,7 @@ import UIKit
...
@@ -9,7 +9,7 @@ import UIKit
class
TodayCoordinator
:
Coordinator
{
class
TodayCoordinator
:
Coordinator
{
//Private
//Private
private
let
todayViewModel
=
TodayViewModel
(
)
private
let
todayViewModel
=
TodayViewModel
(
locationManager
:
LocationManager
.
shared
)
// TODO: get rid of singleton maybe?
private
let
navigationController
=
UINavigationController
(
nibName
:
nil
,
bundle
:
nil
)
private
let
navigationController
=
UINavigationController
(
nibName
:
nil
,
bundle
:
nil
)
private
var
tabBarController
:
UITabBarController
?
private
var
tabBarController
:
UITabBarController
?
...
...
1Weather/Model/LocationManager.swift
View file @
5d1529f8
...
@@ -14,18 +14,47 @@ public protocol LocationManagerDelegate: class {
...
@@ -14,18 +14,47 @@ public protocol LocationManagerDelegate: class {
public
class
LocationManager
{
public
class
LocationManager
{
private
let
log
=
Logger
(
componentName
:
"LocationManager"
)
private
let
log
=
Logger
(
componentName
:
"LocationManager"
)
private
let
delegates
=
MulticastDelegate
<
LocationManagerDelegate
>
()
private
let
delegates
=
MulticastDelegate
<
LocationManagerDelegate
>
()
private
let
weatherUpdateSource
:
WeatherSource
public
static
let
shared
=
LocationManager
(
weatherUpdateSource
:
WdtWeatherSource
())
public
init
(
weatherUpdateSource
:
WeatherSource
)
{
self
.
weatherUpdateSource
=
weatherUpdateSource
}
public
var
currentLocation
:
Location
?
{
public
var
currentLocation
:
Location
?
{
didSet
{
didSet
{
if
currentLocation
!=
oldValue
{
if
oldValue
?
.
description
!=
currentLocation
?
.
description
{
log
.
info
(
"Current location changed to:
\(
currentLocation
?
.
description
??
"nil"
)
"
)
log
.
info
(
"Current location changed to:
\(
currentLocation
?
.
description
??
"nil"
)
"
)
delegates
.
invoke
{
[
weak
self
]
(
delegate
)
in
}
guard
let
self
=
self
else
{
return
}
log
.
info
(
"Location updated."
)
delegate
.
locationManager
(
self
,
changedCurrentLocation
:
currentLocation
)
delegates
.
invoke
{
[
weak
self
]
(
delegate
)
in
guard
let
self
=
self
else
{
return
}
delegate
.
locationManager
(
self
,
changedCurrentLocation
:
currentLocation
)
}
}
}
public
func
updateWeather
()
{
guard
let
location
=
currentLocation
else
{
log
.
warning
(
"Update weather: no location."
)
return
}
log
.
info
(
"Update weather for location:
\(
location
)
"
)
weatherUpdateSource
.
updateWeather
(
for
:
location
)
{
[
weak
self
]
(
updatedLocation
,
error
)
in
guard
let
self
=
self
else
{
return
}
guard
let
updatedLocation
=
updatedLocation
else
{
if
let
error
=
error
{
self
.
log
.
error
(
"Update weather error:
\(
error
)
"
)
}
else
{
self
.
log
.
error
(
"Update weather error: unknown error"
)
}
}
return
}
}
else
{
log
.
debug
(
"location updated without changing"
)
DispatchQueue
.
main
.
async
{
self
.
currentLocation
=
updatedLocation
}
}
}
}
}
}
...
...
1Weather/Model/ModelObjects/Location.swift
View file @
5d1529f8
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
import
Foundation
import
Foundation
import
CoreLocation
import
CoreLocation
public
struct
Location
:
CustomStringConvertible
,
Equatable
{
public
struct
Location
:
CustomStringConvertible
{
// MARK: - Data fields
// MARK: - Data fields
public
var
coordinates
:
CLLocationCoordinate2D
?
public
var
coordinates
:
CLLocationCoordinate2D
?
public
var
imageName
:
String
?
=
"ny_bridge"
//we'll possibly need to switch to URL
public
var
imageName
:
String
?
=
"ny_bridge"
//we'll possibly need to switch to URL
...
@@ -39,6 +39,7 @@ public struct Location: CustomStringConvertible, Equatable {
...
@@ -39,6 +39,7 @@ public struct Location: CustomStringConvertible, Equatable {
public
var
zip
:
String
?
public
var
zip
:
String
?
public
var
fipsCode
:
String
?
public
var
fipsCode
:
String
?
public
var
timeZone
:
TimeZone
public
var
today
:
CurrentWeather
?
public
var
today
:
CurrentWeather
?
public
var
daily
:
[
DailyWeather
]
=
[
DailyWeather
]()
public
var
daily
:
[
DailyWeather
]
=
[
DailyWeather
]()
...
@@ -57,20 +58,6 @@ public struct Location: CustomStringConvertible, Equatable {
...
@@ -57,20 +58,6 @@ public struct Location: CustomStringConvertible, Equatable {
return
"
\(
cityId
)
(no coordinates)"
return
"
\(
cityId
)
(no coordinates)"
}
}
}
}
public
static
func
==
(
lhs
:
Location
,
rhs
:
Location
)
->
Bool
{
// Should we compare the weather here, too?
// TODO: implement
#warning("Not implemented!")
#if DEBUG
//TODO: REMOVE THIS'
return
false
#warning("THIS IS A DEBUG-ONLY PIECE OF CODE! Not even temporary! Remove before making a production build.")
#else
#error("THIS IS A DEBUG-ONLY PIECE OF CODE! Not even temporary! Remove before making a production build.")
#endif
}
}
}
// MARK: - UpdatableModelObject implementation
// MARK: - UpdatableModelObject implementation
...
...
1Weather/Network/Model/HelperObjects/WdtWeatherCode.swift
View file @
5d1529f8
...
@@ -117,8 +117,6 @@ enum WdtWeatherCode: String, Codable {
...
@@ -117,8 +117,6 @@ enum WdtWeatherCode: String, Codable {
case
.
mostlyCloudy
,
.
overcast
:
case
.
mostlyCloudy
,
.
overcast
:
//TODO: handle mostly cloudy night
//TODO: handle mostly cloudy night
return
.
mostlyCloudyDay
return
.
mostlyCloudyDay
default
:
return
.
unknown
}
}
}
}
}
}
1Weather/Network/Model/WdtDailySummary.swift
View file @
5d1529f8
...
@@ -46,7 +46,7 @@ struct WdtDailySummary: Codable {
...
@@ -46,7 +46,7 @@ struct WdtDailySummary: Codable {
dateFormatter
.
dateFormat
=
"MM/dd/YYYY"
dateFormatter
.
dateFormat
=
"MM/dd/YYYY"
dateFormatter
.
timeZone
=
timeZone
dateFormatter
.
timeZone
=
timeZone
guard
let
date
=
dateFormatter
.
date
(
from
:
dateLocal
)
else
{
guard
let
date
=
dateFormatter
.
date
(
from
:
dateLocal
)
else
{
throw
WdtWeatherSourceError
.
dataMergeError
throw
WdtWeatherSourceError
.
dataMergeError
(
"daily.date:
\(
dateLocal
)
"
)
}
}
var
weekDay
=
WeekDay
(
rawValue
:
self
.
weekDay
)
var
weekDay
=
WeekDay
(
rawValue
:
self
.
weekDay
)
...
@@ -56,7 +56,7 @@ struct WdtDailySummary: Codable {
...
@@ -56,7 +56,7 @@ struct WdtDailySummary: Codable {
weekDay
=
WeekDay
(
grigorianWeekDayNumber
:
calendar
.
component
(
.
weekday
,
from
:
date
))
weekDay
=
WeekDay
(
grigorianWeekDayNumber
:
calendar
.
component
(
.
weekday
,
from
:
date
))
}
}
guard
let
weekDayUnwrapped
=
weekDay
else
{
guard
let
weekDayUnwrapped
=
weekDay
else
{
throw
WdtWeatherSourceError
.
dataMergeError
throw
WdtWeatherSourceError
.
dataMergeError
(
"daily.weekday:
\(
self
.
weekDay
)
"
)
}
}
var
result
=
DailyWeather
(
date
:
date
,
timeZone
:
timeZone
,
weekDay
:
weekDayUnwrapped
)
var
result
=
DailyWeather
(
date
:
date
,
timeZone
:
timeZone
,
weekDay
:
weekDayUnwrapped
)
...
@@ -75,7 +75,7 @@ struct WdtDailySummary: Codable {
...
@@ -75,7 +75,7 @@ struct WdtDailySummary: Codable {
let
sunMoonDateFormatter
=
DateFormatter
()
let
sunMoonDateFormatter
=
DateFormatter
()
sunMoonDateFormatter
.
timeZone
=
TimeZone
(
identifier
:
"UTC"
)
sunMoonDateFormatter
.
timeZone
=
TimeZone
(
identifier
:
"UTC"
)
sunMoonDateFormatter
.
dateFormat
=
"YYYY-MM-dd
hh
:mm:ss"
sunMoonDateFormatter
.
dateFormat
=
"YYYY-MM-dd
HH
:mm:ss"
if
let
sunriseUtc
=
sunriseUtc
{
if
let
sunriseUtc
=
sunriseUtc
{
result
.
sunrise
=
sunMoonDateFormatter
.
date
(
from
:
sunriseUtc
)
result
.
sunrise
=
sunMoonDateFormatter
.
date
(
from
:
sunriseUtc
)
}
}
...
...
1Weather/Network/Model/WdtHourlySummary.swift
View file @
5d1529f8
...
@@ -36,11 +36,11 @@ struct WdtHourlySummary: Codable {
...
@@ -36,11 +36,11 @@ struct WdtHourlySummary: Codable {
func
toAppModel
(
timeZone
:
TimeZone
)
throws
->
HourlyWeather
{
func
toAppModel
(
timeZone
:
TimeZone
)
throws
->
HourlyWeather
{
let
dateFormatter
=
DateFormatter
()
let
dateFormatter
=
DateFormatter
()
dateFormatter
.
dateFormat
=
"YYYY-MM-dd
hh
:mm:ss"
dateFormatter
.
dateFormat
=
"YYYY-MM-dd
HH
:mm:ss"
dateFormatter
.
timeZone
=
timeZone
dateFormatter
.
timeZone
=
timeZone
guard
let
date
=
dateFormatter
.
date
(
from
:
self
.
dateTimeLocal
)
else
{
guard
let
date
=
dateFormatter
.
date
(
from
:
self
.
dateTimeLocal
)
else
{
throw
WdtWeatherSourceError
.
dataMergeError
throw
WdtWeatherSourceError
.
dataMergeError
(
"hourly.date:
\(
self
.
dateTimeLocal
)
"
)
}
}
var
weekDay
=
WeekDay
(
rawValue
:
self
.
weekDay
)
var
weekDay
=
WeekDay
(
rawValue
:
self
.
weekDay
)
...
@@ -50,7 +50,7 @@ struct WdtHourlySummary: Codable {
...
@@ -50,7 +50,7 @@ struct WdtHourlySummary: Codable {
weekDay
=
WeekDay
(
grigorianWeekDayNumber
:
calendar
.
component
(
.
weekday
,
from
:
date
))
weekDay
=
WeekDay
(
grigorianWeekDayNumber
:
calendar
.
component
(
.
weekday
,
from
:
date
))
}
}
guard
let
weekDayUnwrapped
=
weekDay
else
{
guard
let
weekDayUnwrapped
=
weekDay
else
{
throw
WdtWeatherSourceError
.
dataMergeError
throw
WdtWeatherSourceError
.
dataMergeError
(
"hourly.weekday:
\(
self
.
weekDay
)
"
)
}
}
let
isDay
=
dayNight
.
trimmingCharacters
(
in
:
.
whitespacesAndNewlines
)
.
lowercased
()
==
"day"
let
isDay
=
dayNight
.
trimmingCharacters
(
in
:
.
whitespacesAndNewlines
)
.
lowercased
()
==
"day"
...
...
1Weather/Network/Model/WdtLocation.swift
View file @
5d1529f8
...
@@ -37,10 +37,19 @@ struct WdtLocation: Codable {
...
@@ -37,10 +37,19 @@ struct WdtLocation: Codable {
if
let
lat
=
CLLocationDegrees
(
lat
??
""
),
let
lon
=
CLLocationDegrees
(
lon
??
""
)
{
if
let
lat
=
CLLocationDegrees
(
lat
??
""
),
let
lon
=
CLLocationDegrees
(
lon
??
""
)
{
coordinates
=
CLLocationCoordinate2D
(
latitude
:
lat
,
longitude
:
lon
)
coordinates
=
CLLocationCoordinate2D
(
latitude
:
lat
,
longitude
:
lon
)
}
}
let
today
=
try
surfaceObservation
.
toAppModel
(
timeZone
:
timeZone
)
var
today
=
try
surfaceObservation
.
toAppModel
(
timeZone
:
timeZone
)
let
dailyWeather
=
try
dailySummaries
?
.
toAppModel
(
timeZone
:
timeZone
)
??
[
DailyWeather
]()
let
dailyWeather
=
try
dailySummaries
?
.
toAppModel
(
timeZone
:
timeZone
)
??
[
DailyWeather
]()
let
hourlyWeather
=
try
hourlySummaries
?
.
toAppModel
(
timeZone
:
timeZone
)
??
[
HourlyWeather
]()
let
hourlyWeather
=
try
hourlySummaries
?
.
toAppModel
(
timeZone
:
timeZone
)
??
[
HourlyWeather
]()
if
let
firstDay
=
dailyWeather
.
first
{
today
.
minTemp
=
firstDay
.
minTemp
today
.
maxTemp
=
firstDay
.
maxTemp
today
.
precipitationProbability
=
firstDay
.
precipitationProbability
today
.
sunState
=
firstDay
.
sunState
today
.
moonState
=
firstDay
.
moonState
today
.
moonPhase
=
firstDay
.
moonPhase
}
return
Location
(
coordinates
:
coordinates
,
return
Location
(
coordinates
:
coordinates
,
imageName
:
nil
,
imageName
:
nil
,
countryCode
:
nil
,
countryCode
:
nil
,
...
@@ -50,6 +59,7 @@ struct WdtLocation: Codable {
...
@@ -50,6 +59,7 @@ struct WdtLocation: Codable {
nickname
:
nil
,
nickname
:
nil
,
zip
:
zipcode
,
zip
:
zipcode
,
fipsCode
:
nil
,
fipsCode
:
nil
,
timeZone
:
timeZone
,
today
:
today
,
today
:
today
,
daily
:
dailyWeather
,
daily
:
dailyWeather
,
hourly
:
hourlyWeather
)
hourly
:
hourlyWeather
)
...
...
1Weather/Network/Model/WdtSurfaceObservation.swift
View file @
5d1529f8
...
@@ -42,11 +42,11 @@ struct WdtSurfaceObservation: Codable {
...
@@ -42,11 +42,11 @@ struct WdtSurfaceObservation: Codable {
public
func
toAppModel
(
timeZone
:
TimeZone
)
throws
->
CurrentWeather
{
public
func
toAppModel
(
timeZone
:
TimeZone
)
throws
->
CurrentWeather
{
let
dateFormatter
=
DateFormatter
()
let
dateFormatter
=
DateFormatter
()
dateFormatter
.
dateFormat
=
"YYYY-MM-dd
hh
:mm:ss"
dateFormatter
.
dateFormat
=
"YYYY-MM-dd
HH
:mm:ss"
dateFormatter
.
timeZone
=
timeZone
dateFormatter
.
timeZone
=
timeZone
guard
let
date
=
dateFormatter
.
date
(
from
:
self
.
dateTimeLocal
)
else
{
guard
let
date
=
dateFormatter
.
date
(
from
:
self
.
dateTimeLocal
)
else
{
throw
WdtWeatherSourceError
.
dataMergeError
throw
WdtWeatherSourceError
.
dataMergeError
(
"today.date:
\(
dateTimeLocal
)
"
)
}
}
var
weekDay
=
WeekDay
(
rawValue
:
self
.
weekDay
)
var
weekDay
=
WeekDay
(
rawValue
:
self
.
weekDay
)
if
weekDay
==
nil
{
if
weekDay
==
nil
{
...
@@ -55,7 +55,7 @@ struct WdtSurfaceObservation: Codable {
...
@@ -55,7 +55,7 @@ struct WdtSurfaceObservation: Codable {
weekDay
=
WeekDay
(
grigorianWeekDayNumber
:
calendar
.
component
(
.
weekday
,
from
:
date
))
weekDay
=
WeekDay
(
grigorianWeekDayNumber
:
calendar
.
component
(
.
weekday
,
from
:
date
))
}
}
guard
let
weekDayUnwrapped
=
weekDay
else
{
guard
let
weekDayUnwrapped
=
weekDay
else
{
throw
WdtWeatherSourceError
.
dataMergeError
throw
WdtWeatherSourceError
.
dataMergeError
(
"today.weekday:
\(
self
.
weekDay
)
"
)
}
}
let
isDay
=
dayNight
.
trimmingCharacters
(
in
:
.
whitespacesAndNewlines
)
.
lowercased
()
==
"day"
let
isDay
=
dayNight
.
trimmingCharacters
(
in
:
.
whitespacesAndNewlines
)
.
lowercased
()
==
"day"
...
@@ -64,13 +64,6 @@ struct WdtSurfaceObservation: Codable {
...
@@ -64,13 +64,6 @@ struct WdtSurfaceObservation: Codable {
if
let
weatherCode
=
self
.
weatherCode
{
if
let
weatherCode
=
self
.
weatherCode
{
result
.
type
=
WdtWeatherCode
(
rawValue
:
weatherCode
)?
.
toAppModel
()
??
.
unknown
result
.
type
=
WdtWeatherCode
(
rawValue
:
weatherCode
)?
.
toAppModel
()
??
.
unknown
}
}
// TODO: gotta fill up values from daily:
// minTemp
// maxTemp
// precipitationProbability
// sunState
// moonState
// moonPhase
result
.
windSpeed
=
WindSpeed
(
valueString
:
self
.
windSpeedKph
,
unit
:
.
kilometersPerHour
)
result
.
windSpeed
=
WindSpeed
(
valueString
:
self
.
windSpeedKph
,
unit
:
.
kilometersPerHour
)
result
.
windDirection
=
WindDirection
(
rawValue
:
windDirection
??
""
)
result
.
windDirection
=
WindDirection
(
rawValue
:
windDirection
??
""
)
...
...
1Weather/Network/WdtWeatherSource.swift
View file @
5d1529f8
...
@@ -13,7 +13,7 @@ public enum WdtWeatherSourceError: Error {
...
@@ -13,7 +13,7 @@ public enum WdtWeatherSourceError: Error {
case
badUrl
case
badUrl
case
networkError
(
Error
?)
case
networkError
(
Error
?)
case
badServerResponse
(
Error
?)
case
badServerResponse
(
Error
?)
case
dataMergeError
case
dataMergeError
(
String
)
}
}
public
class
WdtWeatherSource
:
WeatherSource
{
public
class
WdtWeatherSource
:
WeatherSource
{
...
@@ -58,10 +58,11 @@ public class WdtWeatherSource: WeatherSource {
...
@@ -58,10 +58,11 @@ public class WdtWeatherSource: WeatherSource {
let
decoder
=
XMLDecoder
()
let
decoder
=
XMLDecoder
()
do
{
do
{
let
locationResponse
=
try
decoder
.
decode
(
WdtLocationResponse
.
self
,
from
:
data
)
let
locationResponse
=
try
decoder
.
decode
(
WdtLocationResponse
.
self
,
from
:
data
)
guard
let
newLocation
=
self
.
update
(
location
:
location
,
from
:
locationResponse
)
else
{
guard
let
newLocation
=
try
self
.
update
(
location
:
location
,
from
:
locationResponse
)
else
{
completion
(
nil
,
WdtWeatherSourceError
.
badServerResponse
(
error
))
completion
(
nil
,
WdtWeatherSourceError
.
badServerResponse
(
error
))
return
return
}
}
completion
(
newLocation
,
nil
)
completion
(
newLocation
,
nil
)
}
}
catch
{
catch
{
...
@@ -71,29 +72,12 @@ public class WdtWeatherSource: WeatherSource {
...
@@ -71,29 +72,12 @@ public class WdtWeatherSource: WeatherSource {
dataTask
.
resume
()
dataTask
.
resume
()
}
}
func
update
(
location
:
Location
,
from
locationResponse
:
WdtLocationResponse
)
->
Location
?
{
func
update
(
location
:
Location
,
from
locationResponse
:
WdtLocationResponse
)
throws
->
Location
?
{
// guard let wdtLocation = locationResponse.locations.first else {
guard
let
wdtLocation
=
locationResponse
.
locations
.
first
else
{
// return nil
return
nil
// }
}
var
updatedLocation
=
location
let
incrementalChanges
=
try
wdtLocation
.
toAppModel
(
timeZone
:
location
.
timeZone
)
// if updatedLocation.coordinates == nil {
let
updatedLocation
=
location
.
mergedWith
(
incrementalChanges
:
incrementalChanges
)
// if let lat = CLLocationDegrees(wdtLocation.lat ?? ""), let lon = CLLocationDegrees(wdtLocation.lon ?? "") {
// location.coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
// }
// }
// if updatedLocation.cityName == nil {
// updatedLocation.cityName = wdtLocation.city
// }
// if updatedLocation.countryName == nil {
// updatedLocation.countryName = wdtLocation.country
// }
// if updatedLocation.region == nil {
// updatedLocation.
// }
//
// TOOD: implement
#warning("Not implemented!")
return
updatedLocation
return
updatedLocation
}
}
}
}
1Weather/UI/View controllers/Today/TodayViewController.swift
View file @
5d1529f8
...
@@ -35,6 +35,9 @@ class TodayViewController: UIViewController {
...
@@ -35,6 +35,9 @@ class TodayViewController: UIViewController {
prepareViewController
()
prepareViewController
()
prepareNavigationBar
()
prepareNavigationBar
()
prepareTableView
()
prepareTableView
()
viewModel
.
delegate
=
self
viewModel
.
updateWeather
()
}
}
override
func
viewWillTransition
(
to
size
:
CGSize
,
with
coordinator
:
UIViewControllerTransitionCoordinator
)
{
override
func
viewWillTransition
(
to
size
:
CGSize
,
with
coordinator
:
UIViewControllerTransitionCoordinator
)
{
...
@@ -120,3 +123,9 @@ extension TodayViewController: UITableViewDelegate {
...
@@ -120,3 +123,9 @@ extension TodayViewController: UITableViewDelegate {
viewModel
.
todayCellFactory
.
willDisplay
(
cell
:
cell
)
viewModel
.
todayCellFactory
.
willDisplay
(
cell
:
cell
)
}
}
}
}
extension
TodayViewController
:
ViewModelDelegate
{
func
viewModelDidChange
<
P
>
(
model
:
P
)
where
P
:
ViewModelProtocol
{
tableView
.
reloadData
()
}
}
1Weather/ViewModels/TodayViewModel.swift
View file @
5d1529f8
...
@@ -6,108 +6,38 @@
...
@@ -6,108 +6,38 @@
//
//
import
UIKit
import
UIKit
class
TodayViewModel
{
class
TodayViewModel
:
ViewModelProtocol
{
//Public
//Public
public
let
todayCellFactory
=
TodayCellFactory
()
public
let
todayCellFactory
=
TodayCellFactory
()
public
weak
var
delegate
:
ViewModelDelegate
?
public
weak
var
delegate
:
ViewModelDelegate
?
public
private(set)
var
location
:
Location
public
private(set)
var
location
:
Location
?
private
var
locationManager
:
LocationManager
init
()
{
public
init
(
locationManager
:
LocationManager
)
{
func
weekDay
(
byIndex
:
Int
)
->
WeekDay
{
self
.
locationManager
=
locationManager
switch
byIndex
{
locationManager
.
add
(
delegate
:
self
)
case
0
:
return
.
monday
case
1
:
return
.
tuesday
case
2
:
return
.
wednesday
case
3
:
return
.
thursday
case
4
:
return
.
friday
case
5
:
return
.
saturday
default
:
return
.
sunday
}
}
let
today
=
CurrentWeather
(
date
:
Date
(),
timeZone
:
.
current
,
weekDay
:
.
monday
,
type
:
.
heavyRain
,
isDay
:
true
,
minTemp
:
.
init
(
value
:
-
4
,
unit
:
.
celsius
),
maxTemp
:
.
init
(
value
:
9
,
unit
:
.
celsius
),
windSpeed
:
.
init
(
value
:
5
,
unit
:
.
milesPerHour
),
windDirection
:
.
north
,
precipitationProbability
:
.
some
(
30
),
temp
:
.
init
(
value
:
4
,
unit
:
.
celsius
),
apparentTemp
:
.
init
(
value
:
5
,
unit
:
.
celsius
),
humidity
:
.
some
(
30
),
visibility
:
.
init
(
value
:
8
,
unit
:
.
miles
),
pressure
:
.
init
(
value
:
29.7
,
unit
:
.
inchesOfMercury
),
sunrise
:
.
init
(
hours
:
6
,
minutes
:
26
),
sunset
:
.
init
(
hours
:
17
,
minutes
:
46
),
sunState
:
.
alwaysUp
,
moonrise
:
.
init
(
hours
:
20
,
minutes
:
00
),
moonset
:
.
init
(
hours
:
5
,
minutes
:
30
),
moonState
:
.
normal
)
var
daily
=
[
DailyWeather
]()
var
dailyStartDate
=
Date
()
-
TimeInterval
(
3600
*
24
)
for
index
in
0
..<
7
{
let
day
=
DailyWeather
(
date
:
dailyStartDate
,
timeZone
:
.
current
,
weekDay
:
weekDay
(
byIndex
:
index
),
type
:
WeatherType
.
allCases
.
randomElement
()
??
.
unknown
,
minTemp
:
.
init
(
value
:
Double
.
random
(
in
:
-
3
..<
5
),
unit
:
.
celsius
),
maxTemp
:
.
init
(
value
:
Double
.
random
(
in
:
5
..<
10
),
unit
:
.
celsius
),
windSpeed
:
.
init
(
value
:
Double
.
random
(
in
:
0
..<
10
),
unit
:
.
milesPerHour
),
windDirection
:
WindDirection
.
allCases
.
randomElement
()
??
.
east
,
precipitationProbability
:
.
some
(
UInt
.
random
(
in
:
0
..<
100
)),
sunrise
:
nil
,
sunset
:
nil
,
sunState
:
.
normal
,
moonrise
:
nil
,
moonset
:
nil
,
moonState
:
.
normal
)
dailyStartDate
=
dailyStartDate
+
TimeInterval
(
3600
*
24
)
daily
.
append
(
day
)
}
var
hourly
=
[
HourlyWeather
]()
var
startDate
=
Date
()
-
TimeInterval
(
3600
)
for
_
in
0
..<
24
{
let
hour
=
HourlyWeather
(
date
:
startDate
,
timeZone
:
TimeZone
(
abbreviation
:
"EST"
)
??
.
current
,
weekDay
:
.
monday
,
type
:
WeatherType
.
allCases
.
randomElement
()
??
.
unknown
,
isDay
:
true
,
temp
:
.
init
(
value
:
Double
.
random
(
in
:
-
3
..<
10
),
unit
:
.
celsius
),
windSpeed
:
.
init
(
value
:
Double
.
random
(
in
:
0
..<
10
),
unit
:
.
milesPerHour
),
windDirection
:
WindDirection
.
allCases
.
randomElement
()
??
.
east
,
precipitationProbability
:
.
some
(
UInt
.
random
(
in
:
0
..<
100
)),
humidity
:
.
some
(
UInt
.
random
(
in
:
0
..<
100
)))
startDate
=
startDate
+
TimeInterval
(
3600
)
hourly
.
append
(
hour
)
}
self
.
location
=
Location
(
coordinates
:
nil
,
imageName
:
"ny_bridge"
,
countryCode
:
"us"
,
countryName
:
"United States"
,
region
:
"New York"
,
cityName
:
"New York"
,
nickname
:
"ny"
,
fipsCode
:
"36"
,
today
:
today
,
daily
:
daily
,
hourly
:
hourly
)
//Setup factory callback
//Setup factory callback
todayCellFactory
.
onGetLocation
=
{[
weak
self
]
in
todayCellFactory
.
onGetLocation
=
{[
weak
self
]
in
return
self
?
.
location
return
self
?
.
location
}
}
}
}
public
func
updateWeather
()
{
locationManager
.
updateWeather
()
}
deinit
{
self
.
locationManager
.
remove
(
delegate
:
self
)
}
}
extension
TodayViewModel
:
LocationManagerDelegate
{
func
locationManager
(
_
locationManager
:
LocationManager
,
changedCurrentLocation
newLocation
:
Location
?)
{
DispatchQueue
.
main
.
async
{
print
(
"TVM"
)
self
.
location
=
newLocation
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
}
}
}
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