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
969bf37f
Commit
969bf37f
authored
Mar 26, 2021
by
Demid Merzlyakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Search and location selection working. TODO: location deletion.
parent
355b39f0
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
76 additions
and
32 deletions
+76
-32
1Weather/Info.plist
+2
-0
1Weather/Model/DeviceLocationMonitor.swift
+3
-0
1Weather/Model/LocationManager.swift
+63
-29
1Weather/UI/View controllers/Locations/LocationViewController.swift
+2
-0
1Weather/UI/View controllers/Locations/LocationsViewModel.swift
+2
-0
1Weather/UI/View controllers/Today/TodayViewController.swift
+2
-1
1Weather/ViewModels/ForecastViewModel.swift
+1
-1
1Weather/ViewModels/TodayViewModel.swift
+1
-1
No files found.
1Weather/Info.plist
View file @
969bf37f
...
...
@@ -43,5 +43,7 @@
<
string
>
UIInterfaceOrientationLandscapeLeft
<
/string
>
<
string
>
UIInterfaceOrientationLandscapeRight
<
/string
>
<
/
a
rr
a
y
>
<
k
e
y
>
NSLocationWhenInUseUsageDescription
<
/k
e
y
>
<
string
>
1Weather
uses
your
location
to
provide
you
with
weather
forecasts
and
ads.
For
more
info
visit
1weatherapp.com/privacy
<
/string
>
<
/
d
i
c
t
>
<
/plist
>
1Weather/Model/DeviceLocationMonitor.swift
View file @
969bf37f
...
...
@@ -183,6 +183,9 @@ internal class DeviceLocationMonitor: NSObject {
// MARK: - CLLocationManagerDelegate
extension
DeviceLocationMonitor
:
CLLocationManagerDelegate
{
internal
func
locationManager
(
_
manager
:
CLLocationManager
,
didChangeAuthorization
status
:
CLAuthorizationStatus
)
{
guard
status
!=
.
notDetermined
else
{
return
}
switch
status
{
case
.
denied
:
analytics
(
log
:
.
ANALYTICS_LOC_PERM_NO
)
...
...
1Weather/Model/LocationManager.swift
View file @
969bf37f
...
...
@@ -38,7 +38,11 @@ public class LocationManager {
public
private(set)
var
locations
=
[
Location
]()
{
didSet
{
log
.
info
(
"Locations list updated:
\(
locations
.
map
{
$0
.
description
}
.
joined
(
separator
:
", "
)
)
"
)
let
newValue
=
locations
DispatchQueue
.
main
.
async
{
if
let
selectedIndex
=
self
.
selectedLocationIndex
,
selectedIndex
>=
newValue
.
count
{
self
.
selectedLocationIndex
=
newValue
.
count
>
0
?
0
:
nil
}
self
.
delegates
.
invoke
{
[
weak
self
]
(
delegate
)
in
guard
let
self
=
self
else
{
return
}
delegate
.
locationManager
(
self
,
updatedLocationsList
:
self
.
locations
)
...
...
@@ -47,57 +51,89 @@ public class LocationManager {
}
}
private
var
_selectedLocation
:
Location
?
{
private
var
selectedLocationIndex
:
Int
?
{
didSet
{
if
oldValue
?
.
description
!=
selectedLocation
?
.
description
{
guard
selectedLocationIndex
!=
oldValue
else
{
return
}
var
oldLocation
:
Location
?
if
let
oldValue
=
oldValue
,
oldValue
<
locations
.
count
{
oldLocation
=
locations
[
oldValue
]
}
var
newLocation
:
Location
?
if
let
newValue
=
selectedLocationIndex
,
newValue
<
locations
.
count
{
newLocation
=
locations
[
newValue
]
}
if
oldLocation
?
.
description
!=
newLocation
?
.
description
{
log
.
info
(
"Current location changed to:
\(
selectedLocation
?
.
description
??
"nil"
)
"
)
}
log
.
info
(
"Location updated."
)
DispatchQueue
.
main
.
async
{
self
.
delegates
.
invoke
{
[
weak
self
]
(
delegate
)
in
guard
let
self
=
self
else
{
return
}
delegate
.
locationManager
(
self
,
changedSelectedLocation
:
self
.
selected
Location
)
delegate
.
locationManager
(
self
,
changedSelectedLocation
:
new
Location
)
}
}
self
.
updateWeather
(
for
:
newLocation
)
}
}
public
var
selectedLocation
:
Location
?
{
get
{
guard
let
index
=
selectedLocationIndex
else
{
// TODO: don't do it this way, because we won't be able to tell that no location is currently selected!
return
defaultLocation
}
guard
index
<
locations
.
count
else
{
assertionFailure
(
"This shouldn't happen. Got to investigate."
)
// But in runtime we can handle it gracefully
DispatchQueue
.
main
.
async
{
self
.
selectedLocationIndex
=
self
.
locations
.
count
>
0
?
0
:
nil
}
return
nil
}
return
locations
[
index
]
}
set
{
guard
let
location
=
newValue
else
{
self
.
selectedLocationIndex
=
nil
return
}
if
let
index
=
locations
.
firstIndex
(
of
:
location
)
{
self
.
selectedLocationIndex
=
index
locations
[
index
]
=
location
self
.
delegates
.
invoke
{
[
weak
self
]
(
delegate
)
in
guard
let
self
=
self
else
{
return
}
delegate
.
locationManager
(
self
,
changedSelectedLocation
:
location
)
}
}
else
{
self
.
addIfNeeded
(
location
:
location
,
selectLocation
:
true
)
}
}
}
public
static
let
shared
=
LocationManager
(
weatherUpdateSource
:
WdtWeatherSource
())
public
let
maxLocationsCount
=
12
public
init
(
weatherUpdateSource
:
WeatherSource
)
{
self
.
weatherUpdateSource
=
weatherUpdateSource
self
.
deviceLocationMonitor
=
DeviceLocationMonitor
()
self
.
deviceLocationMonitor
.
delegate
=
self
}
public
var
selectedLocation
:
Location
?
{
get
{
guard
let
location
=
_selectedLocation
else
{
// TODO: don't do it this way! We won't be able to show search if there's no location!
return
defaultLocation
}
return
location
}
set
{
_selectedLocation
=
newValue
}
}
public
func
updateWeather
()
{
guard
let
location
=
selectedLocation
else
{
log
.
warning
(
"Update weather: no location."
)
public
func
updateWeather
(
for
location
:
Location
?)
{
guard
let
location
=
location
else
{
log
.
warning
(
"Update weather: empty location."
)
return
}
if
let
lastTimeUpdated
=
location
.
lastWeatherUpdateDate
{
guard
Date
()
.
timeIntervalSince
(
lastTimeUpdated
)
>=
weatherUpdateSource
.
weatherUpdateInterval
else
{
log
.
info
(
"Update weather: fresh enough (last updated at
\(
l
ocation
.
lastWeatherUpdateDate
)
), skip update."
)
log
.
info
(
"Update weather: fresh enough (last updated at
\(
l
astTimeUpdated
)
), skip update."
)
return
}
}
log
.
info
(
"Update weather for location:
\(
location
)
"
)
weatherUpdateSource
.
updateWeather
(
for
:
location
)
{
[
weak
self
]
(
updatedLocation
,
error
)
in
...
...
@@ -135,22 +171,20 @@ public class LocationManager {
locations
=
[
location
]
+
locations
}
if
selectLocation
{
selectedLocation
=
location
selectedLocation
Index
=
0
}
}
else
if
let
existingLocation
=
locations
.
first
(
where
:
{
$0
==
location
})
{
else
if
let
existingLocation
Index
=
locations
.
firstIndex
(
where
:
{
$0
==
location
})
{
if
selectLocation
{
selectedLocation
=
existingLocation
selectedLocation
Index
=
existingLocationIndex
}
}
else
{
locations
.
append
(
location
)
if
selectLocation
{
selectedLocation
=
location
selectedLocation
Index
=
locations
.
count
-
1
}
}
// TODO: we need to update weather for new locations, probably.
// Or not? Should ViewModels handle it?
}
public
func
addIfNeeded
(
partialLocation
:
PartialLocation
,
selectLocation
:
Bool
)
{
...
...
1Weather/UI/View controllers/Locations/LocationViewController.swift
View file @
969bf37f
...
...
@@ -442,6 +442,8 @@ extension CitiesViewController: UITableViewDelegate {
analytics
(
log
:
.
ANALYTICS_FTUE_SEARCH_POPULAR
)
}
}
self
.
close
()
//TODO: should be done from ViewModel?
}
}
...
...
1Weather/UI/View controllers/Locations/LocationsViewModel.swift
View file @
969bf37f
...
...
@@ -191,6 +191,8 @@ public class LocationsViewModel {
return
}
locationManager
.
addIfNeeded
(
partialLocation
:
city
,
selectLocation
:
true
)
// TODO: close View Controller here, otherwise we can't choose already selected city.
// Currently it's done in the didSelectRow method in the VC.
}
func
delete
(
city
:
PartialLocation
)
{
...
...
1Weather/UI/View controllers/Today/TodayViewController.swift
View file @
969bf37f
...
...
@@ -50,7 +50,8 @@ class TodayViewController: UIViewController {
}
@objc
private
func
handleCityButton
()
{
print
(
"Handle city button"
)
let
locationViewController
=
LocationViewController
(
closeButtonIsHidden
:
false
)
present
(
locationViewController
,
animated
:
true
)
}
@objc
private
func
handleNotificationButton
()
{
...
...
1Weather/ViewModels/ForecastViewModel.swift
View file @
969bf37f
...
...
@@ -31,7 +31,7 @@ class ForecastViewModel: ViewModelProtocol {
}
public
func
updateWeather
()
{
locationManager
.
updateWeather
()
locationManager
.
updateWeather
(
for
:
locationManager
.
selectedLocation
)
}
}
...
...
1Weather/ViewModels/TodayViewModel.swift
View file @
969bf37f
...
...
@@ -31,7 +31,7 @@ class TodayViewModel: ViewModelProtocol {
}
public
func
updateWeather
()
{
locationManager
.
updateWeather
()
locationManager
.
updateWeather
(
for
:
locationManager
.
selectedLocation
)
}
}
...
...
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