-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNetworkObserver.swift
More file actions
116 lines (88 loc) · 3.36 KB
/
NetworkObserver.swift
File metadata and controls
116 lines (88 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
Copyright (C) 2015 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Contains the code to manage the visibility of the network activity indicator
*/
import UIKit
/**
An `OperationObserver` that will cause the network activity indicator to appear
as long as the `Operation` to which it is attached is executing.
*/
struct NetworkObserver: OperationObserver {
// MARK: Initilization
init() { }
func operationDidStart(operation: Operation) {
dispatch_async(dispatch_get_main_queue()) {
// Increment the network indicator's "reference count"
NetworkIndicatorController.sharedIndicatorController.networkActivityDidStart()
}
}
func operation(operation: Operation, didProduceOperation newOperation: NSOperation) { }
func operationDidFinish(operation: Operation, errors: [NSError]) {
dispatch_async(dispatch_get_main_queue()) {
// Decrement the network indicator's "reference count".
NetworkIndicatorController.sharedIndicatorController.networkActivityDidEnd()
}
}
}
/// A singleton to manage a visual "reference count" on the network activity indicator.
private class NetworkIndicatorController {
// MARK: Properties
static let sharedIndicatorController = NetworkIndicatorController()
private var activityCount = 0
private var visibilityTimer: Timer?
// MARK: Methods
func networkActivityDidStart() {
assert(NSThread.isMainThread(), "Altering network activity indicator state can only be done on the main thread.")
activityCount += 1
updateIndicatorVisibility()
}
func networkActivityDidEnd() {
assert(NSThread.isMainThread(), "Altering network activity indicator state can only be done on the main thread.")
activityCount -= 1
updateIndicatorVisibility()
}
private func updateIndicatorVisibility() {
if activityCount > 0 {
showIndicator()
}
else {
/*
To prevent the indicator from flickering on and off, we delay the
hiding of the indicator by one second. This provides the chance
to come in and invalidate the timer before it fires.
*/
visibilityTimer = Timer(interval: 1.0) {
self.hideIndicator()
}
}
}
private func showIndicator() {
visibilityTimer?.cancel()
visibilityTimer = nil
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
private func hideIndicator() {
visibilityTimer?.cancel()
visibilityTimer = nil
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}
}
/// Essentially a cancellable `dispatch_after`.
class Timer {
// MARK: Properties
private var isCancelled = false
// MARK: Initialization
init(interval: NSTimeInterval, handler: dispatch_block_t) {
let when = dispatch_time(DISPATCH_TIME_NOW, Int64(interval * Double(NSEC_PER_SEC)))
dispatch_after(when, dispatch_get_main_queue()) { [weak self] in
if self?.isCancelled == false {
handler()
}
}
}
func cancel() {
isCancelled = true
}
}