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
e1ae935a
Commit
e1ae935a
authored
Apr 22, 2021
by
Demid Merzlyakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Alerts parsing is working.
parent
e45681f9
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
68 additions
and
10 deletions
+68
-10
1Weather.xcodeproj/xcshareddata/xcschemes/1Weather.xcscheme
+1
-1
1Weather/Model/LocationManager.swift
+13
-0
1Weather/Model/ModelObjects/Notifications/Notifications.swift
+1
-1
1Weather/Network/Notifications/Model/NWSAlert.swift
+0
-1
1Weather/Network/Notifications/NWSAlertInfoParser.swift
+9
-3
1Weather/Network/Notifications/NWSAlertsManager.swift
+43
-3
1Weather/UI/View controllers/Today/Cells/TodayAlertCell.swift
+1
-1
No files found.
1Weather.xcodeproj/xcshareddata/xcschemes/1Weather.xcscheme
View file @
e1ae935a
...
@@ -72,7 +72,7 @@
...
@@ -72,7 +72,7 @@
buildConfiguration =
"Debug"
>
buildConfiguration =
"Debug"
>
</AnalyzeAction>
</AnalyzeAction>
<ArchiveAction
<ArchiveAction
buildConfiguration =
"
Debug
"
buildConfiguration =
"
Release
"
revealArchiveInOrganizer =
"YES"
>
revealArchiveInOrganizer =
"YES"
>
</ArchiveAction>
</ArchiveAction>
</Scheme>
</Scheme>
1Weather/Model/LocationManager.swift
View file @
e1ae935a
...
@@ -166,6 +166,8 @@ public class LocationManager {
...
@@ -166,6 +166,8 @@ public class LocationManager {
self
.
storage
=
storage
self
.
storage
=
storage
self
.
deviceLocationMonitor
.
delegate
=
self
self
.
deviceLocationMonitor
.
delegate
=
self
self
.
nwsAlertsManager
.
delegate
=
self
storage
.
load
{
[
weak
self
]
(
locations
,
selectedIndex
,
error
)
in
storage
.
load
{
[
weak
self
]
(
locations
,
selectedIndex
,
error
)
in
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
guard
let
self
=
self
else
{
return
}
guard
let
self
=
self
else
{
return
}
...
@@ -473,3 +475,14 @@ extension LocationManager: DeviceLocationMonitorDelegate {
...
@@ -473,3 +475,14 @@ extension LocationManager: DeviceLocationMonitorDelegate {
}
}
}
}
}
}
// MARK: - NWSAlertsManagerDelegate
extension
LocationManager
:
NWSAlertsManagerDelegate
{
public
func
extendedInfoAvailable
(
from
alertsManager
:
NWSAlertsManager
,
for
alert
:
NWSAlert
)
{
DispatchQueue
.
main
.
async
{
if
let
alertIndex
=
self
.
selectedLocation
?
.
notifications
?
.
nwsAlerts
.
firstIndex
(
of
:
alert
)
{
self
.
selectedLocation
?
.
notifications
?
.
nwsAlerts
[
alertIndex
]
=
alert
}
}
}
}
1Weather/Model/ModelObjects/Notifications/Notifications.swift
View file @
e1ae935a
...
@@ -9,5 +9,5 @@ import Foundation
...
@@ -9,5 +9,5 @@ import Foundation
public
struct
Notifications
{
public
struct
Notifications
{
public
let
updatedAt
:
Date
public
let
updatedAt
:
Date
public
let
nwsAlerts
:
[
NWSAlert
]
public
var
nwsAlerts
:
[
NWSAlert
]
}
}
1Weather/Network/Notifications/Model/NWSAlert.swift
View file @
e1ae935a
...
@@ -8,7 +8,6 @@
...
@@ -8,7 +8,6 @@
import
Foundation
import
Foundation
public
struct
NWSAlert
:
Codable
,
Equatable
,
Hashable
{
public
struct
NWSAlert
:
Codable
,
Equatable
,
Hashable
{
public
var
issueDate
:
Date
?
public
let
weatherID
:
String
public
let
weatherID
:
String
public
let
messageID
:
String
public
let
messageID
:
String
public
let
messageURL
:
String
public
let
messageURL
:
String
...
...
1Weather/Network/Notifications/NWSAlertInfoParser.swift
View file @
e1ae935a
...
@@ -18,8 +18,7 @@ class NWSAlertInfoParser {
...
@@ -18,8 +18,7 @@ class NWSAlertInfoParser {
}
}
let
urlSession
=
URLSession
.
shared
let
urlSession
=
URLSession
.
shared
urlSession
.
dataTask
(
with
:
url
)
{
[
weak
self
]
(
data
,
response
,
error
)
in
urlSession
.
dataTask
(
with
:
url
)
{
(
data
,
response
,
error
)
in
guard
let
self
=
self
else
{
return
}
if
let
httpResponse
=
response
as?
HTTPURLResponse
{
if
let
httpResponse
=
response
as?
HTTPURLResponse
{
guard
httpResponse
.
statusCode
>=
200
&&
httpResponse
.
statusCode
<
400
else
{
guard
httpResponse
.
statusCode
>=
200
&&
httpResponse
.
statusCode
<
400
else
{
log
.
error
(
"HTTP error
\(
httpResponse
.
statusCode
)
"
)
log
.
error
(
"HTTP error
\(
httpResponse
.
statusCode
)
"
)
...
@@ -32,9 +31,16 @@ class NWSAlertInfoParser {
...
@@ -32,9 +31,16 @@ class NWSAlertInfoParser {
completion
(
nil
)
completion
(
nil
)
return
return
}
}
log
.
debug
(
"Response:
\(
responseString
)
"
)
let
extendedInfo
:
NWSAlertExtendedInfo
=
self
.
parseExtendedInfo
(
from
:
responseString
)
let
extendedInfo
:
NWSAlertExtendedInfo
=
self
.
parseExtendedInfo
(
from
:
responseString
)
let
debugEncoder
=
JSONEncoder
()
debugEncoder
.
outputFormatting
=
.
prettyPrinted
debugEncoder
.
dateEncodingStrategy
=
.
iso8601
if
let
jsonData
=
try
?
debugEncoder
.
encode
(
extendedInfo
),
let
json
=
String
(
data
:
jsonData
,
encoding
:
.
utf8
)
{
log
.
debug
(
"Parsed:
\(
json
)
"
)
}
completion
(
extendedInfo
)
completion
(
extendedInfo
)
}
}
.
resume
()
}
}
// MARK: - Private methods
// MARK: - Private methods
...
...
1Weather/Network/Notifications/NWSAlertsManager.swift
View file @
e1ae935a
...
@@ -15,7 +15,12 @@ public enum NWSError: Error {
...
@@ -15,7 +15,12 @@ public enum NWSError: Error {
case
badServerResponse
(
Error
?)
case
badServerResponse
(
Error
?)
}
}
public
protocol
NWSAlertsManagerDelegate
:
class
{
func
extendedInfoAvailable
(
from
alertsManager
:
NWSAlertsManager
,
for
alert
:
NWSAlert
)
}
public
class
NWSAlertsManager
{
public
class
NWSAlertsManager
{
public
weak
var
delegate
:
NWSAlertsManagerDelegate
?
public
typealias
Completion
=
([
NWSAlert
]?,
NWSError
?)
->
()
public
typealias
Completion
=
([
NWSAlert
]?,
NWSError
?)
->
()
#if DEBUG
#if DEBUG
public
let
updateInterval
=
TimeInterval
(
2
*
60
)
// 2 minutes
public
let
updateInterval
=
TimeInterval
(
2
*
60
)
// 2 minutes
...
@@ -33,11 +38,12 @@ public class NWSAlertsManager {
...
@@ -33,11 +38,12 @@ public class NWSAlertsManager {
private
let
log
=
Logger
(
componentName
:
"NWSAlertsManager"
)
private
let
log
=
Logger
(
componentName
:
"NWSAlertsManager"
)
private
var
locationsBeingUpdated
=
Set
<
Location
>
()
private
var
locationsBeingUpdated
=
Set
<
Location
>
()
private
var
extendedInfoBeingFetched
=
Set
<
NWSAlert
>
()
private
var
baseUrl
:
String
{
private
var
baseUrl
:
String
{
useStaging
?
baseUrlStaging
:
baseUrlProduction
useStaging
?
baseUrlStaging
:
baseUrlProduction
}
}
/// This queue is needed to synchronize access to locationsBeingUpdated and
the alerts list
. Also, to make logging more clear.
/// This queue is needed to synchronize access to locationsBeingUpdated and
extendedInfoBeingFetched
. Also, to make logging more clear.
private
let
internalQueue
:
OperationQueue
=
{
private
let
internalQueue
:
OperationQueue
=
{
let
queue
=
OperationQueue
()
let
queue
=
OperationQueue
()
queue
.
name
=
"WdtWeatherSource Queue"
queue
.
name
=
"WdtWeatherSource Queue"
...
@@ -66,6 +72,10 @@ public class NWSAlertsManager {
...
@@ -66,6 +72,10 @@ public class NWSAlertsManager {
}
}
}
}
public
func
extendedInfo
(
for
alert
:
NWSAlert
)
->
NWSAlertExtendedInfo
?
{
return
alerts
.
first
(
where
:
{
$0
==
alert
})?
.
extendedInfo
}
private
func
fetchActiveAlertsInternal
(
for
location
:
Location
,
completion
:
@escaping
NWSAlertsManager
.
Completion
)
{
private
func
fetchActiveAlertsInternal
(
for
location
:
Location
,
completion
:
@escaping
NWSAlertsManager
.
Completion
)
{
guard
!
locationsBeingUpdated
.
contains
(
location
)
else
{
guard
!
locationsBeingUpdated
.
contains
(
location
)
else
{
completion
(
nil
,
.
alreadyBeingUpdated
)
completion
(
nil
,
.
alreadyBeingUpdated
)
...
@@ -133,6 +143,7 @@ public class NWSAlertsManager {
...
@@ -133,6 +143,7 @@ public class NWSAlertsManager {
self
.
merge
(
alerts
:
eventsWithLocation
)
self
.
merge
(
alerts
:
eventsWithLocation
)
completion
(
eventsWithLocation
,
nil
)
completion
(
eventsWithLocation
,
nil
)
}
}
catch
{
catch
{
completion
(
nil
,
.
badServerResponse
(
error
))
completion
(
nil
,
.
badServerResponse
(
error
))
...
@@ -141,7 +152,35 @@ public class NWSAlertsManager {
...
@@ -141,7 +152,35 @@ public class NWSAlertsManager {
dataTask
.
resume
()
dataTask
.
resume
()
}
}
func
merge
(
alerts
newAlerts
:
[
NWSAlert
])
{
private
func
fetchAllExtendedInfo
(
for
alerts
:
[
NWSAlert
])
{
internalQueue
.
addOperation
{
[
weak
self
]
in
guard
let
self
=
self
else
{
return
}
var
newAlertsToFetch
=
[
NWSAlert
]()
let
parser
=
NWSAlertInfoParser
()
for
alert
in
alerts
{
if
!
self
.
extendedInfoBeingFetched
.
contains
(
alert
)
{
self
.
extendedInfoBeingFetched
.
insert
(
alert
)
parser
.
fetchExtendedInfo
(
for
:
alert
)
{
[
weak
self
]
(
extendedInfo
)
in
DispatchQueue
.
main
.
async
{
[
weak
self
]
in
guard
let
self
=
self
else
{
return
}
guard
let
alertIndex
=
self
.
alerts
.
firstIndex
(
where
:
{
$0
==
alert
})
else
{
return
}
self
.
alerts
[
alertIndex
]
.
extendedInfo
=
extendedInfo
self
.
internalQueue
.
addOperation
{
self
.
extendedInfoBeingFetched
.
remove
(
alert
)
}
self
.
delegate
?
.
extendedInfoAvailable
(
from
:
self
,
for
:
self
.
alerts
[
alertIndex
])
}
}
}
}
}
}
private
func
merge
(
alerts
newAlerts
:
[
NWSAlert
])
{
//TODO: optimize
//TODO: optimize
var
resultingSet
=
Set
<
NWSAlert
>
()
var
resultingSet
=
Set
<
NWSAlert
>
()
for
alert
in
self
.
alerts
{
for
alert
in
self
.
alerts
{
...
@@ -150,7 +189,7 @@ public class NWSAlertsManager {
...
@@ -150,7 +189,7 @@ public class NWSAlertsManager {
}
}
}
}
for
alert
in
newAlerts
{
for
alert
in
newAlerts
{
if
!
alert
.
expired
{
if
!
alert
.
expired
&&
!
resultingSet
.
contains
(
alert
)
{
resultingSet
.
insert
(
alert
)
resultingSet
.
insert
(
alert
)
}
}
}
}
...
@@ -163,5 +202,6 @@ public class NWSAlertsManager {
...
@@ -163,5 +202,6 @@ public class NWSAlertsManager {
DispatchQueue
.
main
.
sync
{
DispatchQueue
.
main
.
sync
{
self
.
alerts
=
resultingAlerts
self
.
alerts
=
resultingAlerts
}
}
fetchAllExtendedInfo
(
for
:
resultingAlerts
)
}
}
}
}
1Weather/UI/View controllers/Today/Cells/TodayAlertCell.swift
View file @
e1ae935a
...
@@ -83,7 +83,7 @@ class TodayAlertCell: UITableViewCell {
...
@@ -83,7 +83,7 @@ class TodayAlertCell: UITableViewCell {
infoLabel
.
text
=
infoTemplate
infoLabel
.
text
=
infoTemplate
if
let
issueDate
=
mostSevereAlert
.
issueDate
{
if
let
extendedInfo
=
mostSevereAlert
.
extendedInfo
,
let
issueDate
=
extendedInfo
.
issueDate
{
let
secondsAgo
=
Date
()
.
timeIntervalSince
(
issueDate
)
let
secondsAgo
=
Date
()
.
timeIntervalSince
(
issueDate
)
let
formatter
=
DateComponentsFormatter
()
let
formatter
=
DateComponentsFormatter
()
formatter
.
allowedUnits
=
[
.
day
,
.
hour
,
.
minute
,
.
second
]
formatter
.
allowedUnits
=
[
.
day
,
.
hour
,
.
minute
,
.
second
]
...
...
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