-
Notifications
You must be signed in to change notification settings - Fork 0
/
Webber.swift
233 lines (203 loc) · 8.59 KB
/
Webber.swift
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
//
// Webber.swift
// Webber
//
// Created by Seyyed Parsa Neshaei on 3/12/17.
// Copyright © 2017 Seyyed Parsa Neshaei. All rights reserved.
//
import Foundation
import SystemConfiguration
public class Webber {
/**
Set this property to be used as server address once.
*/
public static var server = ""
/**
Checks the connection to the Internet.
- Returns: `true` if a valid connection to the Internet is found, otherwise `false`.
*/
public static func isInternetAvailable() -> Bool{
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}
/**
Connects to an API using GET.
- Parameters:
- url: The relative URL to the specified server without slash at the beginning.
- cache: Specifies where should content be loaded or saved in cache when offline.
- Returns: A string containing the server result which may be `nil` if you are offline and `cache` is `false` or if the cache is cleared.
*/
public static func getFromAPI(url: String, cache: Bool = true) -> String?{
let defaults=UserDefaults.standard
var text:String?
if isInternetAvailable(){
do{
let url=URL(string: "\(server)/\(url)")
text=try NSString(contentsOf: url!, encoding: String.Encoding.utf8.rawValue) as String
}catch{
print("Webber Error: \(error.localizedDescription)")
return nil
}
if cache{
defaults.set(text, forKey: "__WEBBER_OFFLINE_getFromAPI_\(server)/\(url)")
}
}else{
if cache{
text=defaults.string(forKey: "__WEBBER_OFFLINE_getFromAPI_\(server)/\(url)")
}
}
return text
}
/**
Connects to an API using GET asynchronous.
- Parameters:
- url: The relative URL to the specified server without slash at the beginning.
- cache: Specifies where should content be loaded or saved in cache when offline.
- offline: If `true`, `completion` is called twice, first after loading cache and then after downloading data, else it is called only once after downloading data.
- completion: Things to do when data is received, for example updating a `UITableView`. The closure receives an optional parameter containing the result.
- atLast: Things to do at last, for example stopping a `UIActivityIndicatorView`.
*/
public static func asyncGetFromAPI(url: String, cache: Bool = true, offline: Bool = true, completion: @escaping (String?) -> Void, atLast: ((Void) -> Void)? = nil){
var text:String?
if offline{
text=cacheGetFromAPI(url: url)
completion(text)
}
let queue=DispatchQueue(label: "WebberAsyncGetFromAPI")
queue.async {
text=getFromAPI(url: url, cache: cache)
DispatchQueue.main.async {
if isInternetAvailable(){
completion(text)
}
if let atLastUnwrapped = atLast{
atLastUnwrapped()
}
}
}
}
/**
Returns the saved cache for a URL.
- Parameters:
- url: The relative URL to the specified server without slash at the beginning.
- Returns: A string containing the cached server result which may be `nil` if no cache is saved or if the cache is cleared.
*/
public static func cacheGetFromAPI(url: String) -> String?{
let defaults=UserDefaults.standard
return defaults.string(forKey: "__WEBBER_OFFLINE_getFromAPI_\(server)/\(url)")
}
/**
Connects to an API using GET and parses the result in JSON.
- Parameters:
- url: The relative URL to the specified server without slash at the beginning.
- cache: Specifies where should content be loaded or saved in cache when offline.
- Returns: An array containing the server result parsed to JSON which may be `nil` if you are offline and `cache` is `false` or if the cache is cleared.
*/
public static func getJSONArrayFromAPI(url: String, cache: Bool = true) -> [Any]?{
let defaults=UserDefaults.standard
var text:String?
var arr:[Any]?
if isInternetAvailable(){
do{
let url=URL(string: "\(server)/\(url)")
text=try NSString(contentsOf: url!, encoding: String.Encoding.utf8.rawValue) as String
}catch{
print("Webber Error: \(error.localizedDescription)")
return nil
}
if cache{
defaults.set(text, forKey: "__WEBBER_OFFLINE_getJSONArrayFromAPI_\(server)/\(url)")
}
}else{
if cache{
text=defaults.string(forKey: "__WEBBER_OFFLINE_getJSONArrayFromAPI_\(server)/\(url)")
}
}
do{
if let t=text{
let json = try JSONSerialization.jsonObject(with: t.data(using: String.Encoding.utf8)!, options: [])
if let array=json as? [Any]{
arr=array
}else{
return nil
}
}else{
return nil
}
}catch{
print("Webber Error: \(error.localizedDescription)")
return nil
}
return arr
}
/**
Returns the saved cache parsed to JSON for a URL.
- Parameters:
- url: The relative URL to the specified server without slash at the beginning.
- Returns: An array containing the cached server parsed to JSON result which may be `nil` if no cache is saved or if the cache is cleared.
*/
public static func cacheGetJSONArrayFromAPI(url: String) -> [Any]?{
let defaults=UserDefaults.standard
let text=defaults.string(forKey: "__WEBBER_OFFLINE_getJSONArrayFromAPI_\(server)/\(url)")
var arr:[Any]?
do{
if let t=text{
let json = try JSONSerialization.jsonObject(with: t.data(using: String.Encoding.utf8)!, options: [])
if let array=json as? [Any]{
arr=array
}else{
return nil
}
}else{
return nil
}
}catch{
print("Webber Error: \(error.localizedDescription)")
return nil
}
return arr
}
/**
Connects to an API using GET asynchronous and parses the result to JSON.
- Parameters:
- url: The relative URL to the specified server without slash at the beginning.
- cache: Specifies where should content be loaded or saved in cache when offline.
- offline: If `true`, `completion` is called twice, first after loading cache and then after downloading data, else it is called only once after downloading data.
- completion: Things to do when data is received, for example updating a `UITableView`. The closure receives an optional parameter containing the result parsed to JSON.
- atLast: Things to do at last, for example stopping a `UIActivityIndicatorView`.
*/
public static func asyncGetJSONArrayFromAPI(url: String, cache: Bool = true, offline: Bool = true, completion: @escaping ([Any]?) -> Void, atLast: ((Void) -> Void)? = nil){
var arr:[Any]?
if offline{
arr=cacheGetJSONArrayFromAPI(url: url)
completion(arr)
}
let queue=DispatchQueue(label: "WebberAsyncGetFromAPI")
queue.async {
arr=getJSONArrayFromAPI(url: url, cache: cache)
DispatchQueue.main.async {
if isInternetAvailable(){
completion(arr)
}
if let atLastUnwrapped = atLast{
atLastUnwrapped()
}
}
}
}
}