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
81e13891
Commit
81e13891
authored
Mar 11, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved graph drawning to ForecastTimePeriodView
parent
2b512d82
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
301 additions
and
265 deletions
+301
-265
1Weather.xcodeproj/project.pbxproj
+8
-0
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
+0
-0
1Weather/Model/ModelObjects/ForecastTimePeriod.swift
+13
-0
1Weather/UI/Helpers/ForecastTimePeriodView.swift
+265
-0
1Weather/UI/View controllers/Today/Cells/CityForecastTimePeriod/CityForecastTimePeriodCell.swift
+11
-262
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
+2
-1
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
81e13891
...
...
@@ -27,6 +27,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 */
;
};
CD71709025FA317700A63C27
/* ForecastTimePeriodView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD71708F25FA317700A63C27
/* ForecastTimePeriodView.swift */
;
};
CD71709325FA31C200A63C27
/* ForecastTimePeriod.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD71709225FA31C200A63C27
/* ForecastTimePeriod.swift */
;
};
CD80917B2578E4A8003541A4
/* UIViewController+Alert.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
;
};
CD822FF525D6817000A05501
/* CityForecastCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FF425D6817000A05501
/* CityForecastCell.swift */
;
};
CD822FFA25D6890900A05501
/* OneWeatherColorsAsset.xcassets in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FF925D6890900A05501
/* OneWeatherColorsAsset.xcassets */
;
};
...
...
@@ -110,6 +112,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>"
;
};
CD71708F25FA317700A63C27
/* ForecastTimePeriodView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastTimePeriodView.swift
;
sourceTree
=
"<group>"
;
};
CD71709225FA31C200A63C27
/* ForecastTimePeriod.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastTimePeriod.swift
;
sourceTree
=
"<group>"
;
};
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"UIViewController+Alert.swift"
;
sourceTree
=
"<group>"
;
};
CD822FF425D6817000A05501
/* CityForecastCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CityForecastCell.swift
;
sourceTree
=
"<group>"
;
};
CD822FF925D6890900A05501
/* OneWeatherColorsAsset.xcassets */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
folder.assetcatalog
;
path
=
OneWeatherColorsAsset.xcassets
;
sourceTree
=
"<group>"
;
};
...
...
@@ -419,6 +423,7 @@
CDC6126525E9085600188DA7
/* GraphLine.swift */
,
CD86246B25E6826A0097F3FB
/* InnerShadowLayer.swift */
,
CDC6126925E90C8800188DA7
/* GraphLineSettings.swift */
,
CD71708F25FA317700A63C27
/* ForecastTimePeriodView.swift */
,
);
path
=
Helpers
;
sourceTree
=
"<group>"
;
...
...
@@ -491,6 +496,7 @@
CEAFF08B25DFC6BC00DF4EBF
/* DailyWeather.swift */
,
CEAFF08E25DFC6ED00DF4EBF
/* HourlyWeather.swift */
,
CE578FD225F7E89400E8B85D
/* DayTimeWeather.swift */
,
CD71709225FA31C200A63C27
/* ForecastTimePeriod.swift */
,
);
path
=
ModelObjects
;
sourceTree
=
"<group>"
;
...
...
@@ -662,6 +668,7 @@
CD9B6B1425DBCDE2001D9B80
/* GraphView.swift in Sources */
,
CD39F2EE25DE858D009FE398
/* NotificationName+Localization.swift in Sources */
,
CEAFF08F25DFC6ED00DF4EBF
/* HourlyWeather.swift in Sources */
,
CD71709025FA317700A63C27
/* ForecastTimePeriodView.swift in Sources */
,
CDE18DD825D16CB200C80ED9
/* NavigationCityButton.swift in Sources */
,
CD17C60225D15C8500EE884E
/* CoordinatorProtocol.swift in Sources */
,
CDA5542825EF734200A2E08C
/* TodayCellFactory.swift in Sources */
,
...
...
@@ -675,6 +682,7 @@
CDEE8AD725DA882200C289DE
/* PeriodForecastButton.swift in Sources */
,
CDE18DD125D166F900C80ED9
/* ForecastViewController.swift in Sources */
,
CD39F2F525DE9571009FE398
/* ArrowButton.swift in Sources */
,
CD71709325FA31C200A63C27
/* ForecastTimePeriod.swift in Sources */
,
CEDE4E8325EEFD56007457E9
/* WdtLocationResponse.swift in Sources */
,
CDC6125325E79C8F00188DA7
/* DayTimeView.swift in Sources */
,
CD86246925E672A20097F3FB
/* PrecipButton.swift in Sources */
,
...
...
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
81e13891
...
...
@@ -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 @
81e13891
No preview for this file type
1Weather/Model/ModelObjects/ForecastTimePeriod.swift
0 → 100644
View file @
81e13891
//
// ForecastTimePeriod.swift
// 1Weather
//
// Created by Dmitry Stepanets on 11.03.2021.
//
import
UIKit
struct
ForecastTimePeriod
{
let
daily
:[
DailyWeather
]
let
hourly
:[
HourlyWeather
]
}
1Weather/UI/Helpers/ForecastTimePeriodView.swift
0 → 100644
View file @
81e13891
//
// ForecastView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 11.03.2021.
//
import
UIKit
enum
TimePeriod
:
Int
{
case
daily
=
0
case
hourly
=
1
}
private
struct
DailyGraphPoints
{
let
maxTempPoints
:
[
CGPoint
]
let
minTempPoints
:
[
CGPoint
]
}
private
struct
HourlyGraphPoints
{
let
points
:
[
CGPoint
]
}
class
ForecastTimePeriodView
:
UIView
{
//Private
private
let
scrollView
=
UIScrollView
()
private
let
stackView
=
UIStackView
()
private
let
graphView
=
GraphView
()
private
var
graphRect
:
CGRect
=
.
zero
private
var
currentTimePeriod
=
TimePeriod
.
daily
private
var
dailyGraphPoints
=
DailyGraphPoints
(
maxTempPoints
:
[
CGPoint
](),
minTempPoints
:
[
CGPoint
]())
private
var
hourlyGraphPoints
=
HourlyGraphPoints
(
points
:
[
CGPoint
]())
private
var
forecastTimePeriod
:
ForecastTimePeriod
=
ForecastTimePeriod
(
daily
:
[
DailyWeather
](),
hourly
:
[
HourlyWeather
]())
{
didSet
{
rebuildButtons
()
}
}
init
()
{
super
.
init
(
frame
:
.
zero
)
preapreView
()
prepareScrollView
()
prepareStackView
()
prepareGraphView
()
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
//Public
public
func
set
(
forecastTimePeriod
:
ForecastTimePeriod
)
{
self
.
forecastTimePeriod
=
forecastTimePeriod
}
public
func
set
(
timePeriod
:
TimePeriod
)
{
self
.
currentTimePeriod
=
timePeriod
rebuildButtons
()
}
//Private
private
func
rebuildButtons
()
{
stackView
.
arrangedSubviews
.
forEach
{
stackView
.
removeArrangedSubview
(
$0
)
$0
.
removeFromSuperview
()
}
switch
currentTimePeriod
{
case
.
daily
:
for
index
in
0
..<
forecastTimePeriod
.
daily
.
count
{
let
forecastButton
=
PeriodForecastButton
()
forecastButton
.
configure
(
dailyWeather
:
forecastTimePeriod
.
daily
[
index
])
forecastButton
.
index
=
index
forecastButton
.
addTarget
(
self
,
action
:
#selector(
handleForecastButton(button:)
)
,
for
:
.
touchUpInside
)
forecastButton
.
isSelected
=
index
==
1
stackView
.
addArrangedSubview
(
forecastButton
)
}
case
.
hourly
:
for
index
in
0
..<
forecastTimePeriod
.
hourly
.
count
{
let
forecastButton
=
PeriodForecastButton
()
forecastButton
.
configure
(
hourlyWeather
:
forecastTimePeriod
.
hourly
[
index
])
forecastButton
.
index
=
index
forecastButton
.
addTarget
(
self
,
action
:
#selector(
handleForecastButton(button:)
)
,
for
:
.
touchUpInside
)
forecastButton
.
isSelected
=
index
==
1
stackView
.
addArrangedSubview
(
forecastButton
)
}
}
stackView
.
layoutIfNeeded
()
updateGraphLayout
()
}
private
func
updateGraphLayout
()
{
print
(
"[ForecastTimePeriod] Update graph layout"
)
graphRect
=
(
stackView
.
arrangedSubviews
.
first
as?
PeriodForecastButton
)?
.
graphRect
??
.
zero
graphView
.
frame
=
.
init
(
x
:
0
,
y
:
graphRect
.
origin
.
y
,
width
:
stackView
.
frame
.
width
,
height
:
graphRect
.
height
)
updateGraphPoints
()
drawGraph
()
}
private
func
updateGraphPoints
()
{
switch
currentTimePeriod
{
case
.
daily
:
updateDailyGraphPoints
()
case
.
hourly
:
updateHourlyGraphPoints
()
}
}
private
func
updateDailyGraphPoints
()
{
let
daysCount
=
forecastTimePeriod
.
daily
.
count
let
maxTemps
=
(
forecastTimePeriod
.
daily
.
map
{
CGFloat
(
$0
.
maxTemp
?
.
localeValue
??
0
)
})
let
topMaxTemp
=
maxTemps
.
max
()
??
0
let
minTemps
=
(
forecastTimePeriod
.
daily
.
map
{
CGFloat
(
$0
.
minTemp
?
.
localeValue
??
0
)
})
let
topMinTemp
=
minTemps
.
max
()
??
0
var
maxPoints
=
[
CGPoint
]()
var
minPoints
=
[
CGPoint
]()
for
index
in
0
..<
daysCount
{
guard
let
stackButton
=
stackView
.
arrangedSubviews
[
index
]
as?
PeriodForecastButton
else
{
continue
}
let
buttonRightSide
=
stackButton
.
frame
.
origin
.
x
+
stackButton
.
bounds
.
width
let
buttonCenterX
=
(
buttonRightSide
+
stackButton
.
frame
.
origin
.
x
)
/
2
let
maxTempLevelsCount
=
CGFloat
(
Set
(
maxTemps
)
.
count
)
let
minTempLevelsCount
=
CGFloat
(
Set
(
minTemps
)
.
count
)
let
totalLevels
=
maxTempLevelsCount
+
minTempLevelsCount
let
levelHeight
=
(
graphView
.
frame
.
height
/
CGFloat
(
totalLevels
))
.
rounded
(
.
down
)
let
maxTempFrame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
graphView
.
frame
.
width
,
height
:
maxTempLevelsCount
*
levelHeight
)
let
minTempFrame
=
CGRect
(
x
:
0
,
y
:
maxTempFrame
.
height
,
width
:
graphView
.
frame
.
width
,
height
:
minTempLevelsCount
*
levelHeight
)
//Max
var
maxPointLevel
=
maxTempFrame
.
origin
.
y
+
((
topMaxTemp
-
maxTemps
[
index
])
*
levelHeight
)
+
levelHeight
maxPointLevel
=
min
(
maxPointLevel
,
maxTempFrame
.
height
+
5
)
//Min
var
minPointLevel
=
minTempFrame
.
origin
.
y
+
((
topMinTemp
-
minTemps
[
index
])
*
levelHeight
)
+
levelHeight
minPointLevel
=
min
(
minPointLevel
,
minTempFrame
.
height
+
minTempFrame
.
origin
.
y
-
5
)
maxPoints
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
maxPointLevel
))
minPoints
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
minPointLevel
))
}
dailyGraphPoints
=
DailyGraphPoints
(
maxTempPoints
:
maxPoints
,
minTempPoints
:
minPoints
)
}
private
func
updateHourlyGraphPoints
()
{
let
hoursCount
=
forecastTimePeriod
.
hourly
.
count
let
temps
=
(
forecastTimePeriod
.
hourly
.
map
{
CGFloat
(
$0
.
temp
?
.
localeValue
??
0
)
})
let
maxTemp
=
temps
.
max
()
??
0
var
points
=
[
CGPoint
]()
for
index
in
0
..<
hoursCount
{
guard
let
stackButton
=
stackView
.
arrangedSubviews
[
index
]
as?
PeriodForecastButton
else
{
continue
}
let
buttonRightSide
=
stackButton
.
frame
.
origin
.
x
+
stackButton
.
bounds
.
width
let
buttonCenterX
=
(
buttonRightSide
+
stackButton
.
frame
.
origin
.
x
)
/
2
let
levelsCount
=
CGFloat
(
Set
(
temps
)
.
count
)
let
levelHeight
=
(
graphView
.
frame
.
height
/
CGFloat
(
levelsCount
))
.
rounded
(
.
down
)
let
tempFrame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
graphView
.
frame
.
width
,
height
:
graphView
.
frame
.
height
)
var
pointLevel
=
tempFrame
.
origin
.
y
+
((
maxTemp
-
temps
[
index
])
*
levelHeight
)
pointLevel
=
max
(
pointLevel
,
tempFrame
.
origin
.
y
+
10
)
pointLevel
=
min
(
tempFrame
.
height
-
10
,
pointLevel
)
points
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
pointLevel
))
}
hourlyGraphPoints
=
HourlyGraphPoints
(
points
:
points
)
}
private
func
drawGraph
()
{
guard
let
periodButtons
=
stackView
.
arrangedSubviews
as?
[
PeriodForecastButton
],
let
selectedButton
=
(
periodButtons
.
first
{
$0
.
isSelected
})
else
{
return
}
switch
currentTimePeriod
{
case
.
daily
:
self
.
graphView
.
drawMainGraph
(
with
:
dailyGraphPoints
.
maxTempPoints
)
self
.
graphView
.
drawAdditionalGraph
(
with
:
dailyGraphPoints
.
minTempPoints
)
self
.
tintGraphAt
(
button
:
selectedButton
)
case
.
hourly
:
self
.
graphView
.
drawMainGraph
(
with
:
hourlyGraphPoints
.
points
)
self
.
graphView
.
drawAdditionalGraph
(
with
:
[
CGPoint
]())
self
.
tintGraphAt
(
button
:
selectedButton
)
}
print
(
"[ForecastTimePeriod] Draw graph"
)
}
private
func
tintGraphAt
(
button
:
PeriodForecastButton
)
{
switch
currentTimePeriod
{
case
.
daily
:
self
.
graphView
.
tintGraphFrom
(
startPointX
:
button
.
frame
.
origin
.
x
,
endPointX
:
button
.
frame
.
origin
.
x
+
button
.
bounds
.
width
)
self
.
graphView
.
tintMainDotAt
(
point
:
dailyGraphPoints
.
maxTempPoints
[
button
.
index
])
self
.
graphView
.
tintAdditionalDotAt
(
point
:
dailyGraphPoints
.
minTempPoints
[
button
.
index
])
case
.
hourly
:
self
.
graphView
.
tintGraphFrom
(
startPointX
:
button
.
frame
.
origin
.
x
,
endPointX
:
button
.
frame
.
origin
.
x
+
button
.
bounds
.
width
)
self
.
graphView
.
tintMainDotAt
(
point
:
hourlyGraphPoints
.
points
[
button
.
index
])
}
}
@objc
private
func
handleForecastButton
(
button
:
PeriodForecastButton
)
{
stackView
.
arrangedSubviews
.
forEach
{
if
let
periodButton
=
$0
as?
PeriodForecastButton
{
periodButton
.
isSelected
=
periodButton
===
button
if
periodButton
.
isSelected
{
tintGraphAt
(
button
:
periodButton
)
}
}
}
}
}
private
extension
ForecastTimePeriodView
{
func
preapreView
()
{
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
}
func
prepareScrollView
()
{
scrollView
.
showsVerticalScrollIndicator
=
false
scrollView
.
showsHorizontalScrollIndicator
=
false
scrollView
.
clipsToBounds
=
false
addSubview
(
scrollView
)
scrollView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
edges
.
equalToSuperview
()
}
}
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/Today/Cells/CityForecastTimePeriod/CityForecastTimePeriodCell.swift
View file @
81e13891
...
...
@@ -7,48 +7,22 @@
import
UIKit
private
struct
DailyGraphPoints
{
let
maxTempPoints
:
[
CGPoint
]
let
minTempPoints
:
[
CGPoint
]
}
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
(),
"forecast.timePeriod.hourly"
.
localized
()])
private
let
kMinGraphHeight
:
CGFloat
=
20
private
let
scrollView
=
UIScrollView
()
private
let
stackView
=
UIStackView
()
private
let
forecastTimePeriodView
=
ForecastTimePeriodView
()
private
let
summaryView
=
UIView
()
private
let
summaryImageView
=
UIImageView
()
private
let
summaryLabel
=
UILabel
()
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
//MARK:- Cell life cycle
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
prepareCell
()
prepareSegmentedControl
()
prepareScrollView
()
prepareStackView
()
prepareGraphView
()
prepareForecastTimePeriodView
()
prepareSummaryView
()
}
...
...
@@ -58,215 +32,16 @@ class CityForecastTimePeriodCell: UITableViewCell {
//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
()
}
private
func
drawGraph
()
{
guard
let
periodButtons
=
stackView
.
arrangedSubviews
as?
[
PeriodForecastButton
],
let
selectedButton
=
(
periodButtons
.
first
{
$0
.
isSelected
})
else
{
return
}
switch
currentTimePeriod
{
case
.
daily
:
guard
let
maxTempPoints
=
dailyGraphPoints
?
.
maxTempPoints
,
let
minTempsPoints
=
dailyGraphPoints
?
.
minTempPoints
else
{
return
}
self
.
graphView
.
drawMainGraph
(
with
:
maxTempPoints
)
self
.
graphView
.
drawAdditionalGraph
(
with
:
minTempsPoints
)
self
.
tintGraphAt
(
button
:
selectedButton
)
case
.
hourly
:
guard
let
hourlyPoints
=
hourlyGraphPoints
?
.
points
else
{
return
}
self
.
graphView
.
drawMainGraph
(
with
:
hourlyPoints
)
self
.
graphView
.
drawAdditionalGraph
(
with
:
[
CGPoint
]())
self
.
tintGraphAt
(
button
:
selectedButton
)
}
print
(
"Draw graph!"
)
}
private
func
tintGraphAt
(
button
:
PeriodForecastButton
)
{
switch
currentTimePeriod
{
case
.
daily
:
guard
let
maxTempPoints
=
dailyGraphPoints
?
.
maxTempPoints
,
let
minTempsPoints
=
dailyGraphPoints
?
.
minTempPoints
else
{
return
}
self
.
graphView
.
tintGraphFrom
(
startPointX
:
button
.
frame
.
origin
.
x
,
endPointX
:
button
.
frame
.
origin
.
x
+
button
.
bounds
.
width
)
self
.
graphView
.
tintMainDotAt
(
point
:
maxTempPoints
[
button
.
index
])
self
.
graphView
.
tintAdditionalDotAt
(
point
:
minTempsPoints
[
button
.
index
])
case
.
hourly
:
guard
let
points
=
hourlyGraphPoints
?
.
points
else
{
return
}
self
.
graphView
.
tintGraphFrom
(
startPointX
:
button
.
frame
.
origin
.
x
,
endPointX
:
button
.
frame
.
origin
.
x
+
button
.
bounds
.
width
)
self
.
graphView
.
tintMainDotAt
(
point
:
points
[
button
.
index
])
let
forecastTimePeriod
=
ForecastTimePeriod
(
daily
:
location
.
daily
,
hourly
:
location
.
hourly
)
self
.
forecastTimePeriodView
.
set
(
forecastTimePeriod
:
forecastTimePeriod
)
}
}
private
func
updateGraphPoints
(){
switch
currentTimePeriod
{
case
.
daily
:
self
.
updateDailyGraphPoints
()
case
.
hourly
:
self
.
updateHourlyGraphPoints
()
}
}
private
func
updateDailyGraphPoints
()
{
guard
let
daysCount
=
location
?
.
daily
.
count
,
let
maxTemps
=
(
location
?
.
daily
.
map
{
CGFloat
(
$0
.
maxTemp
?
.
localeValue
??
0
)
}),
let
topMaxTemp
=
maxTemps
.
max
(),
let
minTemps
=
(
location
?
.
daily
.
map
{
CGFloat
(
$0
.
minTemp
?
.
localeValue
??
0
)
}),
let
topMinTemp
=
minTemps
.
max
()
else
{
return
}
var
maxPoints
=
[
CGPoint
]()
var
minPoints
=
[
CGPoint
]()
for
index
in
0
..<
daysCount
{
guard
let
stackButton
=
stackView
.
arrangedSubviews
[
index
]
as?
PeriodForecastButton
else
{
continue
}
let
buttonRightSide
=
stackButton
.
frame
.
origin
.
x
+
stackButton
.
bounds
.
width
let
buttonCenterX
=
(
buttonRightSide
+
stackButton
.
frame
.
origin
.
x
)
/
2
let
maxTempLevelsCount
=
CGFloat
(
Set
(
maxTemps
)
.
count
)
let
minTempLevelsCount
=
CGFloat
(
Set
(
minTemps
)
.
count
)
let
totalLevels
=
maxTempLevelsCount
+
minTempLevelsCount
let
levelHeight
=
(
graphView
.
frame
.
height
/
CGFloat
(
totalLevels
))
.
rounded
(
.
down
)
let
maxTempFrame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
graphView
.
frame
.
width
,
height
:
maxTempLevelsCount
*
levelHeight
)
let
minTempFrame
=
CGRect
(
x
:
0
,
y
:
maxTempFrame
.
height
,
width
:
graphView
.
frame
.
width
,
height
:
minTempLevelsCount
*
levelHeight
)
//Max
var
maxPointLevel
=
maxTempFrame
.
origin
.
y
+
((
topMaxTemp
-
maxTemps
[
index
])
*
levelHeight
)
+
levelHeight
maxPointLevel
=
min
(
maxPointLevel
,
maxTempFrame
.
height
+
5
)
//Min
var
minPointLevel
=
minTempFrame
.
origin
.
y
+
((
topMinTemp
-
minTemps
[
index
])
*
levelHeight
)
+
levelHeight
minPointLevel
=
min
(
minPointLevel
,
minTempFrame
.
height
+
minTempFrame
.
origin
.
y
-
5
)
maxPoints
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
maxPointLevel
))
minPoints
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
minPointLevel
))
}
dailyGraphPoints
=
DailyGraphPoints
(
maxTempPoints
:
maxPoints
,
minTempPoints
:
minPoints
)
}
private
func
updateHourlyGraphPoints
()
{
guard
let
hoursCount
=
location
?
.
hourly
.
count
,
let
temps
=
(
location
?
.
hourly
.
map
{
CGFloat
(
$0
.
temp
?
.
localeValue
??
0
)
}),
let
maxTemp
=
temps
.
max
()
else
{
@objc
private
func
handleSegmentDidChange
()
{
guard
let
timePeriod
=
TimePeriod
(
rawValue
:
self
.
periodSegmentedControl
.
selectedSegmentIndex
)
else
{
return
}
var
points
=
[
CGPoint
]()
for
index
in
0
..<
hoursCount
{
guard
let
stackButton
=
stackView
.
arrangedSubviews
[
index
]
as?
PeriodForecastButton
else
{
continue
}
let
buttonRightSide
=
stackButton
.
frame
.
origin
.
x
+
stackButton
.
bounds
.
width
let
buttonCenterX
=
(
buttonRightSide
+
stackButton
.
frame
.
origin
.
x
)
/
2
let
levelsCount
=
CGFloat
(
Set
(
temps
)
.
count
)
let
levelHeight
=
(
graphView
.
frame
.
height
/
CGFloat
(
levelsCount
))
.
rounded
(
.
down
)
let
tempFrame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
graphView
.
frame
.
width
,
height
:
graphView
.
frame
.
height
)
var
pointLevel
=
tempFrame
.
origin
.
y
+
((
maxTemp
-
temps
[
index
])
*
levelHeight
)
pointLevel
=
max
(
pointLevel
,
tempFrame
.
origin
.
y
+
10
)
pointLevel
=
min
(
tempFrame
.
height
-
10
,
pointLevel
)
points
.
append
(
.
init
(
x
:
buttonCenterX
,
y
:
pointLevel
))
}
hourlyGraphPoints
=
HourlyGraphPoints
(
points
:
points
)
}
@objc
private
func
handleConditionButton
(
button
:
PeriodForecastButton
)
{
stackView
.
arrangedSubviews
.
forEach
{
if
let
periodButton
=
$0
as?
PeriodForecastButton
{
periodButton
.
isSelected
=
periodButton
===
button
if
periodButton
.
isSelected
{
tintGraphAt
(
button
:
periodButton
)
}
}
}
}
@objc
private
func
handleSegmentDidChange
()
{
self
.
currentTimePeriod
=
TimePeriod
(
rawValue
:
self
.
periodSegmentedControl
.
selectedSegmentIndex
)
!
self
.
rebuildStackButtons
()
self
.
forecastTimePeriodView
.
set
(
timePeriod
:
timePeriod
)
}
}
...
...
@@ -288,13 +63,9 @@ private extension CityForecastTimePeriodCell {
}
}
func
prepareScrollView
()
{
scrollView
.
showsVerticalScrollIndicator
=
false
scrollView
.
showsHorizontalScrollIndicator
=
false
scrollView
.
clipsToBounds
=
false
contentView
.
addSubview
(
scrollView
)
scrollView
.
snp
.
makeConstraints
{
(
make
)
in
func
prepareForecastTimePeriodView
()
{
contentView
.
addSubview
(
forecastTimePeriodView
)
forecastTimePeriodView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
make
.
right
.
equalToSuperview
()
make
.
top
.
equalTo
(
periodSegmentedControl
.
snp
.
bottom
)
.
offset
(
30
)
.
priority
(
.
medium
)
...
...
@@ -302,28 +73,6 @@ private extension CityForecastTimePeriodCell {
}
}
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
)
}
func
prepareSummaryView
()
{
summaryImageView
.
contentMode
=
.
scaleAspectFit
summaryImageView
.
image
=
UIImage
(
named
:
"hot_indicator"
)
...
...
@@ -353,7 +102,7 @@ private extension CityForecastTimePeriodCell {
summaryView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
right
.
equalToSuperview
()
.
inset
(
18
)
make
.
height
.
equalTo
(
40
)
make
.
top
.
equalTo
(
scroll
View
.
snp
.
bottom
)
.
offset
(
20
)
make
.
top
.
equalTo
(
forecastTimePeriod
View
.
snp
.
bottom
)
.
offset
(
20
)
make
.
bottom
.
equalToSuperview
()
.
inset
(
15
)
}
}
...
...
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
View file @
81e13891
...
...
@@ -83,7 +83,8 @@ class TodayCellFactory {
public
func
willDisplay
(
cell
:
UITableViewCell
)
{
switch
cell
{
case
let
timePeriodCell
as
CityForecastTimePeriodCell
:
timePeriodCell
.
drawGraphIfNeeded
()
break
// timePeriodCell.drawGraphIfNeeded()
case
let
sunCell
as
CitySunCell
:
sunCell
.
updateSunPosition
()
case
let
moonCell
as
CityMoonCell
:
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
81e13891
...
...
@@ -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