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
5faf43ad
Commit
5faf43ad
authored
Mar 10, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on forecast controller
parent
f977bec8
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
433 additions
and
18 deletions
+433
-18
1Weather.xcodeproj/project.pbxproj
+20
-0
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
+0
-0
1Weather/Coordinators/ForecastCoordinator.swift
+5
-2
1Weather/Resources/OneWeatherColorsAsset.xcassets/background_color.colorset/Contents.json
+3
-3
1Weather/UI/Controls/ForecastTimePeriodControl.swift
+5
-0
1Weather/UI/View controllers/Forecast/Cells/ForecastCellFactory.swift
+55
-0
1Weather/UI/View controllers/Forecast/Cells/ForecastTimePeriodCell.swift
+182
-0
1Weather/UI/View controllers/Forecast/ForecastViewController.swift
+108
-2
1Weather/UI/View controllers/Today/Cells/CityDayTimesCell/DayTimeView.swift
+1
-0
1Weather/UI/View controllers/Today/Cells/CityForecastTimePeriod/CityForecastTimePeriodCell.swift
+0
-5
1Weather/ViewModels/ForecastViewModel.swift
+47
-0
1Weather/ViewModels/TodayViewModel.swift
+5
-4
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
5faf43ad
...
...
@@ -40,6 +40,9 @@
CD86246925E672A20097F3FB
/* PrecipButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD86246825E672A20097F3FB
/* PrecipButton.swift */
;
};
CD86246C25E6826A0097F3FB
/* InnerShadowLayer.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD86246B25E6826A0097F3FB
/* InnerShadowLayer.swift */
;
};
CD86C22225F0DCCB00F38A16
/* PrecipView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD86C22125F0DCCB00F38A16
/* PrecipView.swift */
;
};
CD8E040D25F8F3D2001785B6
/* ForecastTimePeriodCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD8E040C25F8F3D2001785B6
/* ForecastTimePeriodCell.swift */
;
};
CD8E041225F8F775001785B6
/* ForecastViewModel.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD8E041125F8F775001785B6
/* ForecastViewModel.swift */
;
};
CD8E041625F8F91B001785B6
/* ForecastCellFactory.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD8E041525F8F91B001785B6
/* ForecastCellFactory.swift */
;
};
CD9B6B1125DBC723001D9B80
/* CubicCurveAlgorithm.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD9B6B1025DBC723001D9B80
/* CubicCurveAlgorithm.swift */
;
};
CD9B6B1425DBCDE2001D9B80
/* GraphView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD9B6B1325DBCDE2001D9B80
/* GraphView.swift */
;
};
CDA5542825EF734200A2E08C
/* TodayCellFactory.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
;
};
...
...
@@ -123,6 +126,9 @@
CD86246825E672A20097F3FB
/* PrecipButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PrecipButton.swift
;
sourceTree
=
"<group>"
;
};
CD86246B25E6826A0097F3FB
/* InnerShadowLayer.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
InnerShadowLayer.swift
;
sourceTree
=
"<group>"
;
};
CD86C22125F0DCCB00F38A16
/* PrecipView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PrecipView.swift
;
sourceTree
=
"<group>"
;
};
CD8E040C25F8F3D2001785B6
/* ForecastTimePeriodCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastTimePeriodCell.swift
;
sourceTree
=
"<group>"
;
};
CD8E041125F8F775001785B6
/* ForecastViewModel.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastViewModel.swift
;
sourceTree
=
"<group>"
;
};
CD8E041525F8F91B001785B6
/* ForecastCellFactory.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastCellFactory.swift
;
sourceTree
=
"<group>"
;
};
CD9B6B1025DBC723001D9B80
/* CubicCurveAlgorithm.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CubicCurveAlgorithm.swift
;
sourceTree
=
"<group>"
;
};
CD9B6B1325DBCDE2001D9B80
/* GraphView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
GraphView.swift
;
sourceTree
=
"<group>"
;
};
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayCellFactory.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -272,6 +278,7 @@
isa
=
PBXGroup
;
children
=
(
CD647D0125ED07D60034578B
/* TodayViewModel.swift */
,
CD8E041125F8F775001785B6
/* ForecastViewModel.swift */
,
CD647D0525ED08050034578B
/* ViewModelProtocol.swift */
,
);
path
=
ViewModels
;
...
...
@@ -352,6 +359,15 @@
path
=
CityPrecipCell
;
sourceTree
=
"<group>"
;
};
CD8E040B25F8F39B001785B6
/* Cells */
=
{
isa
=
PBXGroup
;
children
=
(
CD8E041525F8F91B001785B6
/* ForecastCellFactory.swift */
,
CD8E040C25F8F3D2001785B6
/* ForecastTimePeriodCell.swift */
,
);
path
=
Cells
;
sourceTree
=
"<group>"
;
};
CDC6124D25E7960D00188DA7
/* CityDayTimesCell */
=
{
isa
=
PBXGroup
;
children
=
(
...
...
@@ -426,6 +442,7 @@
CDE18DCF25D166DD00C80ED9
/* Forecast */
=
{
isa
=
PBXGroup
;
children
=
(
CD8E040B25F8F39B001785B6
/* Cells */
,
CDE18DD025D166F900C80ED9
/* ForecastViewController.swift */
,
);
path
=
Forecast
;
...
...
@@ -676,6 +693,7 @@
CDE18DD125D166F900C80ED9
/* ForecastViewController.swift in Sources */
,
CD39F2F525DE9571009FE398
/* ArrowButton.swift in Sources */
,
CEDE4E8325EEFD56007457E9
/* WdtLocationResponse.swift in Sources */
,
CD8E041625F8F91B001785B6
/* ForecastCellFactory.swift in Sources */
,
CDC6125325E79C8F00188DA7
/* DayTimeView.swift in Sources */
,
CD86246925E672A20097F3FB
/* PrecipButton.swift in Sources */
,
CEDE4E8225EEFD56007457E9
/* WdtWeatherCode.swift in Sources */
,
...
...
@@ -703,9 +721,11 @@
CD86245E25E646350097F3FB
/* SunUvView.swift in Sources */
,
CEAFF08325DFC67F00DF4EBF
/* Location.swift in Sources */
,
CD82300725D6A73F00A05501
/* CityConditionButton.swift in Sources */
,
CD8E040D25F8F3D2001785B6
/* ForecastTimePeriodCell.swift in Sources */
,
CDC6126A25E90C8800188DA7
/* GraphLineSettings.swift in Sources */
,
CDA5542D25EF7C9700A2E08C
/* ReusableCellProtocol.swift in Sources */
,
CD647D0625ED08050034578B
/* ViewModelProtocol.swift in Sources */
,
CD8E041225F8F775001785B6
/* ForecastViewModel.swift in Sources */
,
CD86246C25E6826A0097F3FB
/* InnerShadowLayer.swift in Sources */
,
CEAFF0A325E0FF0800DF4EBF
/* LocationManager.swift in Sources */
,
CEAD00A12577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift in Sources */
,
...
...
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
5faf43ad
...
...
@@ -7,7 +7,7 @@
<
k
e
y
>
1Weather.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
6
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
5
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
View file @
5faf43ad
No preview for this file type
1Weather/Coordinators/ForecastCoordinator.swift
View file @
5faf43ad
...
...
@@ -9,6 +9,8 @@ import UIKit
class
ForecastCoordinator
:
Coordinator
{
//Private
private
let
forecastViewModel
=
ForecastViewModel
(
locationManager
:
LocationManager
.
shared
)
private
let
navigationController
=
UINavigationController
(
nibName
:
nil
,
bundle
:
nil
)
private
var
tabBarController
:
UITabBarController
?
//Public
...
...
@@ -20,7 +22,8 @@ class ForecastCoordinator: Coordinator {
}
func
start
()
{
let
forecastViewController
=
ForecastViewController
()
self
.
tabBarController
?
.
add
(
viewController
:
forecastViewController
)
let
forecastViewController
=
ForecastViewController
(
viewModel
:
forecastViewModel
)
navigationController
.
viewControllers
=
[
forecastViewController
]
tabBarController
?
.
add
(
viewController
:
navigationController
)
}
}
1Weather/Resources/OneWeatherColorsAsset.xcassets/background_color.colorset/Contents.json
View file @
5faf43ad
...
...
@@ -5,9 +5,9 @@
"color-space"
:
"srgb"
,
"components"
:
{
"alpha"
:
"1.000"
,
"blue"
:
"
254
"
,
"green"
:
"
24
8"
,
"red"
:
"
24
7"
"blue"
:
"
0xFE
"
,
"green"
:
"
0xF
8"
,
"red"
:
"
0xF
7"
}
},
"idiom"
:
"universal"
...
...
1Weather/UI/Controls/ForecastTimePeriodControl.swift
View file @
5faf43ad
...
...
@@ -7,6 +7,11 @@
import
UIKit
enum
TimePeriod
:
Int
{
case
daily
=
0
case
hourly
=
1
}
class
ForecastTimePeriodControl
:
UISegmentedControl
{
private
let
kTopInset
:
CGFloat
=
2
private
let
kSideInset
:
CGFloat
=
11
...
...
1Weather/UI/View controllers/Forecast/Cells/ForecastCellFactory.swift
0 → 100644
View file @
5faf43ad
//
// ForecastCellFactory.swift
// 1Weather
//
// Created by Dmitry Stepanets on 10.03.2021.
//
import
UIKit
private
enum
ForecastCellType
:
Int
,
CaseIterable
{
case
forecastPeriod
=
0
// case forecast
// case conditions
// case precipitation
// case dayTime
// case sun
// case moon
}
class
ForecastCellFactory
{
public
var
onGetLocation
:(()
->
Location
?)?
public
var
numberOfRows
:
Int
{
return
ForecastCellType
.
allCases
.
count
}
public
func
registerCells
(
on
tableView
:
UITableView
)
{
registerCell
(
type
:
ForecastTimePeriodCell
.
self
,
tableView
:
tableView
)
}
public
func
cellFromTableView
(
tableView
:
UITableView
,
indexPath
:
IndexPath
)
->
UITableViewCell
{
guard
let
cellType
=
ForecastCellType
(
rawValue
:
indexPath
.
row
)
else
{
return
UITableViewCell
()
}
guard
let
loc
=
self
.
onGetLocation
?()
else
{
return
UITableViewCell
()
}
switch
cellType
{
case
.
forecastPeriod
:
let
cell
=
dequeueReusableCell
(
type
:
ForecastTimePeriodCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
return
cell
}
}
//Private
private
func
registerCell
<
T
:
ReusableCellProtocol
>
(
type
:
T
.
Type
,
tableView
:
UITableView
)
{
tableView
.
register
(
type
,
forCellReuseIdentifier
:
T
.
kIdentifier
)
}
private
func
dequeueReusableCell
<
T
:
ReusableCellProtocol
>
(
type
:
T
.
Type
,
tableView
:
UITableView
,
indexPath
:
IndexPath
)
->
T
{
let
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
T
.
kIdentifier
,
for
:
indexPath
)
as!
T
return
cell
}
}
1Weather/UI/View controllers/Forecast/Cells/ForecastTimePeriodCell.swift
0 → 100644
View file @
5faf43ad
//
// ForecastTimePeriodCell.swift
// 1Weather
//
// Created by Dmitry Stepanets on 10.03.2021.
//
import
UIKit
private
struct
DailyGraphPoints
{
let
maxTempPoints
:
[
CGPoint
]
let
minTempPoints
:
[
CGPoint
]
}
private
struct
HourlyGraphPoints
{
let
points
:
[
CGPoint
]
}
class
ForecastTimePeriodCell
:
UITableViewCell
{
//Private
private
let
periodSegmentedControl
=
ForecastTimePeriodControl
(
items
:
[
"forecast.timePeriod.daily"
.
localized
(),
"forecast.timePeriod.hourly"
.
localized
()])
private
let
kMinGraphHeight
:
CGFloat
=
20
private
let
gradientView
=
GradientView
(
startColor
:
UIColor
(
hex
:
0xffffff
)
.
withAlphaComponent
(
0
),
endColor
:
UIColor
(
hex
:
0xdaddec
),
opacity
:
0.5
)
private
let
scrollView
=
UIScrollView
()
private
let
stackView
=
UIStackView
()
private
var
location
:
Location
?
private
var
currentTimePeriod
=
TimePeriod
.
daily
private
var
dailyGraphPoints
:
DailyGraphPoints
?
private
var
hourlyGraphPoints
:
HourlyGraphPoints
?
private
let
graphView
=
GraphView
()
private
var
graphIsDrawn
=
false
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
prepareCell
()
prepareSegmentedControl
()
prepareGradient
()
prepareScrollView
()
prepareStackView
()
prepareGraphView
()
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
//Public
public
func
configure
(
with
location
:
Location
)
{
self
.
location
=
location
rebuildStackButtons
()
}
public
func
drawGraphIfNeeded
()
{
guard
graphIsDrawn
==
false
else
{
return
}
//Checking for correct height
guard
let
periodButton
=
stackView
.
arrangedSubviews
.
first
as?
PeriodForecastButton
,
periodButton
.
graphRect
.
height
>=
kMinGraphHeight
else
{
return
}
graphView
.
frame
=
.
init
(
x
:
0
,
y
:
periodButton
.
graphRect
.
origin
.
y
,
width
:
stackView
.
frame
.
width
,
height
:
periodButton
.
graphRect
.
height
)
updateGraphPoints
()
drawGraph
()
graphIsDrawn
=
true
}
//Private
private
func
rebuildStackButtons
()
{
//Update graph buttons
stackView
.
arrangedSubviews
.
forEach
{
stackView
.
removeArrangedSubview
(
$0
)
$0
.
removeFromSuperview
()
}
guard
let
location
=
self
.
location
else
{
return
}
switch
currentTimePeriod
{
case
.
daily
:
for
index
in
0
..<
location
.
daily
.
count
{
let
conditionButton
=
PeriodForecastButton
()
conditionButton
.
configure
(
dailyWeather
:
location
.
daily
[
index
])
conditionButton
.
index
=
index
conditionButton
.
addTarget
(
self
,
action
:
#selector(
handleConditionButton(button:)
)
,
for
:
.
touchUpInside
)
conditionButton
.
isSelected
=
index
==
1
stackView
.
addArrangedSubview
(
conditionButton
)
}
case
.
hourly
:
for
index
in
0
..<
location
.
hourly
.
count
{
let
conditionButton
=
PeriodForecastButton
()
conditionButton
.
configure
(
hourlyWeather
:
location
.
hourly
[
index
])
conditionButton
.
index
=
index
conditionButton
.
addTarget
(
self
,
action
:
#selector(
handleConditionButton(button:)
)
,
for
:
.
touchUpInside
)
conditionButton
.
isSelected
=
index
==
1
stackView
.
addArrangedSubview
(
conditionButton
)
}
}
stackView
.
layoutIfNeeded
()
graphIsDrawn
=
false
drawGraphIfNeeded
()
}
@objc
private
func
handleSegmentDidChange
()
{
}
}
private
extension
ForecastTimePeriodCell
{
func
prepareCell
()
{
selectionStyle
=
.
none
contentView
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
}
func
prepareSegmentedControl
()
{
periodSegmentedControl
.
selectedSegmentIndex
=
0
periodSegmentedControl
.
addTarget
(
self
,
action
:
#selector(
handleSegmentDidChange
)
,
for
:
.
valueChanged
)
contentView
.
addSubview
(
periodSegmentedControl
)
periodSegmentedControl
.
snp
.
makeConstraints
{
(
make
)
in
make
.
top
.
equalToSuperview
()
.
inset
(
15
)
make
.
left
.
right
.
equalToSuperview
()
.
inset
(
16
)
make
.
height
.
equalTo
(
40
)
}
}
func
prepareGradient
()
{
contentView
.
addSubview
(
gradientView
)
gradientView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
right
.
bottom
.
equalToSuperview
()
make
.
height
.
equalTo
(
172
)
}
}
func
prepareScrollView
()
{
scrollView
.
showsVerticalScrollIndicator
=
false
scrollView
.
showsHorizontalScrollIndicator
=
false
scrollView
.
clipsToBounds
=
false
contentView
.
addSubview
(
scrollView
)
scrollView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
make
.
right
.
equalToSuperview
()
make
.
top
.
equalTo
(
periodSegmentedControl
.
snp
.
bottom
)
.
offset
(
20
)
.
priority
(
.
medium
)
make
.
bottom
.
equalToSuperview
()
.
inset
(
15
)
make
.
height
.
equalTo
(
267
)
}
}
func
prepareStackView
()
{
stackView
.
axis
=
.
horizontal
stackView
.
distribution
=
.
equalSpacing
stackView
.
alignment
=
.
center
stackView
.
spacing
=
10
stackView
.
clipsToBounds
=
false
stackView
.
isLayoutMarginsRelativeArrangement
=
true
stackView
.
layoutMargins
=
.
init
(
top
:
0
,
left
:
6
,
bottom
:
0
,
right
:
6
)
scrollView
.
addSubview
(
stackView
)
stackView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
edges
.
height
.
equalToSuperview
()
}
}
func
prepareGraphView
()
{
//Graph view
graphView
.
frame
=
.
zero
graphView
.
backgroundColor
=
.
clear
scrollView
.
addSubview
(
graphView
)
}
}
1Weather/UI/View controllers/Forecast/ForecastViewController.swift
View file @
5faf43ad
...
...
@@ -8,10 +8,116 @@
import
UIKit
class
ForecastViewController
:
UIViewController
{
//Private
private
let
cityButton
=
NavigationCityButton
()
private
let
tableView
=
UITableView
()
private
let
viewModel
:
ForecastViewModel
private
var
localizationObserver
:
Any
?
init
(
viewModel
:
ForecastViewModel
)
{
self
.
viewModel
=
viewModel
super
.
init
(
nibName
:
nil
,
bundle
:
nil
)
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
view
.
backgroundColor
=
.
blue
viewModel
.
delegate
=
self
prepareViewController
()
prepareNavigationBar
()
prepareTableView
()
refreshCityButton
()
}
private
func
refreshCityButton
()
{
cityButton
.
configure
(
with
:
viewModel
.
location
)
cityButton
.
isHidden
=
false
}
@objc
private
func
handleCityButton
()
{
print
(
"Handle city button"
)
}
@objc
private
func
handleNotificationButton
()
{
print
(
"Handle notification button"
)
}
}
//MARk:- Prepare
private
extension
ForecastViewController
{
func
prepareViewController
()
{
view
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
localizationObserver
=
NotificationCenter
.
default
.
addObserver
(
forName
:
.
localizationChange
,
object
:
nil
,
queue
:
.
main
,
using
:
{
_
in
self
.
tableView
.
reloadData
()
})
}
func
prepareNavigationBar
()
{
//City button
cityButton
.
isHidden
=
true
cityButton
.
addTarget
(
self
,
action
:
#selector(
handleCityButton
)
,
for
:
.
touchUpInside
)
let
cityBarItem
=
UIBarButtonItem
(
customView
:
cityButton
)
let
barSpacer
=
UIBarButtonItem
(
barButtonSystemItem
:
.
fixedSpace
,
target
:
nil
,
action
:
nil
)
barSpacer
.
width
=
18
//Notification button
let
notificationButton
=
UIButton
()
notificationButton
.
frame
=
.
init
(
origin
:
.
zero
,
size
:
.
init
(
width
:
40
,
height
:
40
))
notificationButton
.
setImage
(
UIImage
(
named
:
"bell"
),
for
:
.
normal
)
notificationButton
.
tintColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
notificationButton
.
addTarget
(
self
,
action
:
#selector(
handleNotificationButton
)
,
for
:
.
touchUpInside
)
let
notificationBarButton
=
UIBarButtonItem
(
customView
:
notificationButton
)
notificationButton
.
contentEdgeInsets
=
.
init
(
top
:
0
,
left
:
16
,
bottom
:
0
,
right
:
0
)
self
.
navigationItem
.
leftBarButtonItems
=
[
barSpacer
,
cityBarItem
]
self
.
navigationItem
.
rightBarButtonItem
=
notificationBarButton
}
func
prepareTableView
()
{
viewModel
.
forecastCellFactory
.
registerCells
(
on
:
tableView
)
tableView
.
contentInset
=
.
init
(
top
:
0
,
left
:
0
,
bottom
:
15
,
right
:
0
)
tableView
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
tableView
.
separatorStyle
=
.
none
tableView
.
tableFooterView
=
UIView
()
tableView
.
estimatedRowHeight
=
UITableView
.
automaticDimension
tableView
.
rowHeight
=
UITableView
.
automaticDimension
tableView
.
delegate
=
self
tableView
.
dataSource
=
self
view
.
addSubview
(
tableView
)
tableView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
edges
.
equalToSuperview
()
}
}
}
//MARK:- UITableView Delegate
extension
ForecastViewController
:
UITableViewDelegate
{
}
//MARK:- UITableView DataSource
extension
ForecastViewController
:
UITableViewDataSource
{
func
tableView
(
_
tableView
:
UITableView
,
numberOfRowsInSection
section
:
Int
)
->
Int
{
return
viewModel
.
forecastCellFactory
.
numberOfRows
}
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
)
->
UITableViewCell
{
return
viewModel
.
forecastCellFactory
.
cellFromTableView
(
tableView
:
tableView
,
indexPath
:
indexPath
)
}
}
//MARK:- ViewModel Delegate
extension
ForecastViewController
:
ViewModelDelegate
{
func
viewModelDidChange
<
P
>
(
model
:
P
)
where
P
:
ViewModelProtocol
{
refreshCityButton
()
tableView
.
reloadData
()
}
}
1Weather/UI/View controllers/Today/Cells/CityDayTimesCell/DayTimeView.swift
View file @
5faf43ad
...
...
@@ -32,6 +32,7 @@ class DayTimeView: UIView {
dayTimeLabel
.
text
=
dayTimeWeather
.
dayTime
.
localized
forecastImageView
.
image
=
dayTimeWeather
.
type
.
image
(
isDay
:
dayTimeWeather
.
isDay
)
tempLabel
.
text
=
dayTimeWeather
.
temp
?
.
shortString
??
"--"
dayTimeConditionLabel
.
text
=
dayTimeWeather
.
type
.
localized
(
isDay
:
dayTimeWeather
.
isDay
)
}
}
...
...
1Weather/UI/View controllers/Today/Cells/CityForecastTimePeriod/CityForecastTimePeriodCell.swift
View file @
5faf43ad
...
...
@@ -16,11 +16,6 @@ private struct HourlyGraphPoints {
let
points
:
[
CGPoint
]
}
private
enum
TimePeriod
:
Int
{
case
daily
=
0
case
hourly
=
1
}
class
CityForecastTimePeriodCell
:
UITableViewCell
{
//Private
private
let
periodSegmentedControl
=
ForecastTimePeriodControl
(
items
:
[
"forecast.timePeriod.daily"
.
localized
(),
...
...
1Weather/ViewModels/ForecastViewModel.swift
0 → 100644
View file @
5faf43ad
//
// ForecastViewModel.swift
// 1Weather
//
// Created by Dmitry Stepanets on 10.03.2021.
//
import
UIKit
class
ForecastViewModel
:
ViewModelProtocol
{
//Public
public
let
forecastCellFactory
=
ForecastCellFactory
()
public
weak
var
delegate
:
ViewModelDelegate
?
public
private(set)
var
location
:
Location
?
//Private
private
var
locationManager
:
LocationManager
deinit
{
self
.
locationManager
.
remove
(
delegate
:
self
)
}
public
init
(
locationManager
:
LocationManager
)
{
self
.
locationManager
=
locationManager
locationManager
.
add
(
delegate
:
self
)
//Setup factory callback
forecastCellFactory
.
onGetLocation
=
{[
weak
self
]
in
return
self
?
.
location
}
}
public
func
updateWeather
()
{
locationManager
.
updateWeather
()
}
}
//MARK:- LocationManager Delegate
extension
ForecastViewModel
:
LocationManagerDelegate
{
func
locationManager
(
_
locationManager
:
LocationManager
,
changedCurrentLocation
newLocation
:
Location
?)
{
DispatchQueue
.
main
.
async
{
print
(
"TVM-Forecast"
)
self
.
location
=
newLocation
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
}
}
1Weather/ViewModels/TodayViewModel.swift
View file @
5faf43ad
...
...
@@ -16,6 +16,10 @@ class TodayViewModel: ViewModelProtocol {
//Private
private
var
locationManager
:
LocationManager
deinit
{
self
.
locationManager
.
remove
(
delegate
:
self
)
}
public
init
(
locationManager
:
LocationManager
)
{
self
.
locationManager
=
locationManager
locationManager
.
add
(
delegate
:
self
)
...
...
@@ -29,12 +33,9 @@ class TodayViewModel: ViewModelProtocol {
public
func
updateWeather
()
{
locationManager
.
updateWeather
()
}
deinit
{
self
.
locationManager
.
remove
(
delegate
:
self
)
}
}
//MARK:- LocationManager Delegate
extension
TodayViewModel
:
LocationManagerDelegate
{
func
locationManager
(
_
locationManager
:
LocationManager
,
changedCurrentLocation
newLocation
:
Location
?)
{
DispatchQueue
.
main
.
async
{
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
5faf43ad
...
...
@@ -52,7 +52,7 @@
<
k
e
y
>
XMLCoder.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
5
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
6
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
/
d
i
c
t
>
<
k
e
y
>
SuppressBuildableAutocreation
<
/k
e
y
>
...
...
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