Skip to content

Commit 2957996

Browse files
author
Burak Colak
committed
🎷 [UPDATE] Download progress completed, memory leaks resolved.
1 parent 95be7d4 commit 2957996

File tree

12 files changed

+140
-91
lines changed

12 files changed

+140
-91
lines changed

Sources/ACMNetworking/ACMNetworking.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,41 @@ import Foundation
66

77
/// ACMNetworking, make requests easily
88
public class ACMNetworking: NSObject {
9+
var mainEndpoint: ACMBaseEndpoint?
10+
var session: URLSession?
911
var requestTask: URLSessionDataTask?
1012
var downloadTask: URLSessionDownloadTask?
1113
var taskProgress: NSKeyValueObservation?
1214

15+
/// Predefined variables
16+
var logger: ACMBaseLogger? {
17+
mainEndpoint?.logger
18+
}
19+
20+
var stringUtils: ACMStringUtils? {
21+
mainEndpoint?.stringUtils
22+
}
23+
1324
/// Public Init function
1425
/// For creating object with SDK
1526
override public init() {
1627
super.init()
1728
}
1829

30+
/// Public destroy function
31+
deinit {
32+
print("ACMNetworking deinited")
33+
}
34+
1935
/// Cancels the current network request
2036
public func cancel() {
2137
cancelRequestTask()
2238
cancelDownloadTask()
39+
session?.invalidateAndCancel()
40+
session = nil
41+
taskProgress?.invalidate()
42+
taskProgress = nil
43+
mainEndpoint = nil
2344
}
2445

2546
private func cancelRequestTask() {

Sources/ACMNetworking/Library/Constants/ACMNetworking/ACMNetworkingConstants.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
//
44

55
enum ACMNetworkingConstants {
6-
static var configOverride: Bool = false
6+
static var configOverride: Bool? = false
77
}

Sources/ACMNetworking/Library/Constants/NetworkMessages/ACMNetworkConstants.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ public extension ACMNetworkConstants {
5454
}
5555

5656
/// Header for holding multipart header with content type
57-
static func multipartHeader(model: ACMMultipartContentTypeModel) -> ACMHeaderModel {
58-
ACMHeaderModel(field: "Content-Type", value: ACMStringUtils.shared.merge(list: [
57+
static func multipartHeader(model: ACMMultipartContentTypeModel, utils: ACMStringUtils?) -> ACMHeaderModel {
58+
ACMHeaderModel(field: "Content-Type", value: utils?.merge(list: [
5959
model.type,
6060
" ",
6161
model.boundary,
62-
]))
62+
]) ?? "")
6363
}
6464

6565
/// Header for holding multipart accept type

Sources/ACMNetworking/Library/Extensions/ACMNetworking+Extensions.swift

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,65 @@ import Foundation
77
extension ACMNetworking {
88
func baseRequest(to endpoint: ACMBaseEndpoint) -> URLRequest? {
99
guard let urlRequest = endpoint.urlRequest else {
10-
ACMBaseLogger.error(ACMNetworkConstants.urlRequestErrorMessage)
10+
endpoint.logger?.error(ACMNetworkConstants.urlRequestErrorMessage)
1111
return nil
1212
}
1313

14-
let info = ACMStringUtils.shared.merge(list: [
14+
var infoList = [
1515
ACMNetworkConstants.httpRequestType,
16-
endpoint.method.rawValue,
17-
])
18-
ACMBaseLogger.info(info)
16+
]
17+
18+
if let methodRaw = endpoint.method?.rawValue {
19+
infoList.append(methodRaw)
20+
}
21+
22+
let info = endpoint.stringUtils?.merge(list: infoList)
23+
endpoint.logger?.info(info)
1924

2025
if let url = endpoint.url {
21-
let info = ACMStringUtils.shared.merge(list: [
26+
let info = endpoint.stringUtils?.merge(list: [
2227
ACMNetworkConstants.httpURLMessage,
2328
"\(url)",
2429
])
25-
ACMBaseLogger.info(info)
30+
endpoint.logger?.info(info)
2631
}
2732

2833
if let authHeader = endpoint.authHeader {
29-
let info = ACMStringUtils.shared.merge(list: [
34+
let info = endpoint.stringUtils?.merge(list: [
3035
ACMNetworkConstants.httpAuthHeadersMessage,
3136
"\(authHeader)",
3237
])
33-
ACMBaseLogger.info(info)
38+
endpoint.logger?.info(info)
3439
}
3540

3641
if let headers = endpoint.headers, headers.count > 0 {
37-
let info = ACMStringUtils.shared.merge(list: [
42+
let info = endpoint.stringUtils?.merge(list: [
3843
ACMNetworkConstants.httpHeadersMessage,
3944
"\(headers)",
4045
])
41-
ACMBaseLogger.info(info)
46+
endpoint.logger?.info(info)
4247
}
4348

4449
if let queryItems = endpoint.queryItems, queryItems.count > 0 {
45-
let info = ACMStringUtils.shared.merge(list: [
50+
let info = endpoint.stringUtils?.merge(list: [
4651
ACMNetworkConstants.httpQueryItemsMessage,
4752
"\(queryItems)",
4853
])
49-
ACMBaseLogger.info(info)
54+
endpoint.logger?.info(info)
5055
}
5156

5257
if let params = endpoint.params {
53-
let info = ACMStringUtils.shared.merge(list: [
58+
let info = endpoint.stringUtils?.merge(list: [
5459
ACMNetworkConstants.httpBodyMessage,
5560
params.paramsRaw,
5661
])
57-
ACMBaseLogger.info(info)
62+
endpoint.logger?.info(info)
5863
} else if let data = endpoint.mediaData {
59-
let info = ACMStringUtils.shared.merge(list: [
64+
let info = endpoint.stringUtils?.merge(list: [
6065
ACMNetworkConstants.httpBodyMessage,
6166
String(format: ACMNetworkConstants.httpBodyMultipart, "\(data.length)"),
6267
])
63-
ACMBaseLogger.info(info)
68+
endpoint.logger?.info(info)
6469
}
6570

6671
return urlRequest
@@ -75,13 +80,13 @@ extension ACMNetworking: URLSessionTaskDelegate {
7580
/// - task: URL session task
7681
/// - didFinishCollecting: Metrics that gathered
7782
public func urlSession(_: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
78-
let message = ACMStringUtils.shared.merge(list: [
83+
let message = mainEndpoint?.stringUtils?.merge(list: [
7984
"didFinishCollecting",
8085
task.description,
8186
"metrics",
8287
"\(metrics.taskInterval)",
8388
])
84-
ACMBaseLogger.info(message)
89+
logger?.info(message)
8590
}
8691

8792
/// URL Session taskIsWaitingForConnectivity
@@ -90,11 +95,11 @@ extension ACMNetworking: URLSessionTaskDelegate {
9095
/// - session: URL Session
9196
/// - task: URL session task
9297
public func urlSession(_: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
93-
let message = ACMStringUtils.shared.merge(list: [
98+
let message = mainEndpoint?.stringUtils?.merge(list: [
9499
"taskIsWaitingForConnectivity",
95100
task.description,
96101
])
97-
ACMBaseLogger.info(message)
102+
logger?.info(message)
98103
}
99104

100105
/// URL Session didSendBodyData
@@ -106,7 +111,7 @@ extension ACMNetworking: URLSessionTaskDelegate {
106111
/// - totalBytesSent
107112
/// - totalBytesExpectedToSend
108113
public func urlSession(_: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
109-
let message = ACMStringUtils.shared.merge(list: [
114+
let message = mainEndpoint?.stringUtils?.merge(list: [
110115
"task",
111116
task.description,
112117
"didSendBodyData",
@@ -116,6 +121,6 @@ extension ACMNetworking: URLSessionTaskDelegate {
116121
"totalBytesExpectedToSend",
117122
"\(totalBytesExpectedToSend)",
118123
])
119-
ACMBaseLogger.info(message)
124+
logger?.info(message)
120125
}
121126
}

Sources/ACMNetworking/Library/Extensions/ACMNetworking+Handle+Extensions.swift

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
extension ACMNetworking {
1111
func generateURLRequest(endpoint: ACMBaseEndpoint) -> URLRequest? {
1212
guard let urlRequest = baseRequest(to: endpoint) else {
13-
ACMBaseLogger.error(ACMNetworkConstants.urlRequestErrorMessage)
13+
endpoint.logger?.error(ACMNetworkConstants.urlRequestErrorMessage)
1414
return nil
1515
}
1616
return urlRequest
@@ -22,11 +22,12 @@ extension ACMNetworking {
2222
func handleNilErrorResponse(with endpoint: ACMBaseEndpoint, error: Error?, onError: ACMGenericCallbacks.ErrorCallback) {
2323
guard error == nil else {
2424
cancel()
25-
let message = ACMStringUtils.shared.merge(list: [
25+
26+
let message = endpoint.stringUtils?.merge(list: [
2627
ACMNetworkConstants.errorMessage,
2728
error?.localizedDescription ?? "",
2829
])
29-
ACMBaseLogger.error(message)
30+
endpoint.logger?.error(message)
3031
onError?(ACMBaseNetworkError(message: ACMNetworkConstants.errorMessage, log: error?.localizedDescription, endpoint: endpoint))
3132
return
3233
}
@@ -38,11 +39,11 @@ extension ACMNetworking {
3839
func handleNilResponse(with endpoint: ACMBaseEndpoint, response: URLResponse?, onError: ACMGenericCallbacks.ErrorCallback) {
3940
guard response != nil else {
4041
cancel()
41-
let message = ACMStringUtils.shared.merge(list: [
42+
let message = endpoint.stringUtils?.merge(list: [
4243
ACMNetworkConstants.errorMessage,
4344
ACMNetworkConstants.responseNullMessage,
4445
])
45-
ACMBaseLogger.error(message)
46+
endpoint.logger?.error(message)
4647
onError?(ACMBaseNetworkError(message: ACMNetworkConstants.errorMessage, log: ACMNetworkConstants.responseNullMessage, endpoint: endpoint))
4748
return
4849
}
@@ -54,11 +55,11 @@ extension ACMNetworking {
5455
func handleConnectivityError(with endpoint: ACMBaseEndpoint, error: Error?, onError: ACMGenericCallbacks.ErrorCallback) {
5556
if error?.isConnectivityError ?? false {
5657
cancel()
57-
let message = ACMStringUtils.shared.merge(list: [
58+
let message = endpoint.stringUtils?.merge(list: [
5859
ACMNetworkConstants.errorMessage,
5960
ACMNetworkConstants.dataNullMessage,
6061
])
61-
ACMBaseLogger.error(message)
62+
endpoint.logger?.error(message)
6263
onError?(ACMBaseNetworkError(message: ACMNetworkConstants.errorMessage, log: ACMNetworkConstants.dataNullMessage, endpoint: endpoint))
6364
return
6465
}
@@ -70,11 +71,11 @@ extension ACMNetworking {
7071
func handleData(with endpoint: ACMBaseEndpoint, data: Data?, onError: ACMGenericCallbacks.ErrorCallback) -> Data? {
7172
guard let data = data else {
7273
cancel()
73-
let message = ACMStringUtils.shared.merge(list: [
74+
let message = endpoint.stringUtils?.merge(list: [
7475
ACMNetworkConstants.errorMessage,
7576
ACMNetworkConstants.dataNullMessage,
7677
])
77-
ACMBaseLogger.error(message)
78+
endpoint.logger?.error(message)
7879
onError?(ACMBaseNetworkError(message: ACMNetworkConstants.errorMessage, log: ACMNetworkConstants.dataNullMessage, endpoint: endpoint))
7980
return nil
8081
}
@@ -87,11 +88,11 @@ extension ACMNetworking {
8788
func handleHttpResponse(with endpoint: ACMBaseEndpoint, response: URLResponse?, onError: ACMGenericCallbacks.ErrorCallback) -> HTTPURLResponse? {
8889
guard let httpResponse = response as? HTTPURLResponse else {
8990
cancel()
90-
let message = ACMStringUtils.shared.merge(list: [
91+
let message = endpoint.stringUtils?.merge(list: [
9192
ACMNetworkConstants.errorMessage,
9293
ACMNetworkConstants.httpStatusError,
9394
])
94-
ACMBaseLogger.error(message)
95+
endpoint.logger?.error(message)
9596
onError?(ACMBaseNetworkError(message: ACMNetworkConstants.errorMessage, log: ACMNetworkConstants.httpStatusError, endpoint: endpoint))
9697
return nil
9798
}
@@ -109,14 +110,14 @@ extension ACMNetworking {
109110
extension ACMNetworking {
110111
/// Execute retry mechanism
111112
func executeRetry<T: Decodable>(with endpoint: ACMBaseEndpoint, httpResponse: HTTPURLResponse, data: Data, currentRetryCount: Int?, onSuccess: ACMGenericCallbacks.ResponseCallback<T>, onError: ACMGenericCallbacks.ErrorCallback) {
112-
let message = ACMStringUtils.shared.merge(list: [
113+
let message = endpoint.stringUtils?.merge(list: [
113114
ACMNetworkConstants.errorMessage,
114115
ACMNetworkConstants.httpStatusError,
115116
"-\(httpResponse.statusCode)",
116117
ACMNetworkConstants.responseInfoMessage,
117118
String(data: data, encoding: .utf8) ?? "",
118119
])
119-
ACMBaseLogger.error(message)
120+
endpoint.logger?.error(message)
120121

121122
// MARK: Retry mechanism
122123

@@ -128,7 +129,7 @@ extension ACMNetworking {
128129

129130
if let currentRetryCount = currentRetryCount, currentRetryCount < maxRetryCount {
130131
let nextRetryCount = currentRetryCount + 1
131-
ACMBaseLogger.info(ACMStringUtils.shared.merge(list: [
132+
endpoint.logger?.info(endpoint.stringUtils?.merge(list: [
132133
String(format: ACMNetworkConstants.httpRetryCount, nextRetryCount, maxRetryCount),
133134
]))
134135
request(to: endpoint, currentRetryCount: nextRetryCount, onSuccess: onSuccess, onError: onError)
@@ -143,11 +144,11 @@ extension ACMNetworking {
143144
func handleResult<T: Decodable>(with endpoint: ACMBaseEndpoint, data: Data, onSuccess: ACMGenericCallbacks.ResponseCallback<T>, onError: ACMGenericCallbacks.ErrorCallback) {
144145
do {
145146
let dataString = String(data: data, encoding: .utf8) ?? ""
146-
let info = ACMStringUtils.shared.merge(list: [
147+
let info = endpoint.stringUtils?.merge(list: [
147148
ACMNetworkConstants.responseInfoMessage,
148149
dataString,
149150
])
150-
ACMBaseLogger.info(info)
151+
endpoint.logger?.info(info)
151152

152153
if endpoint.isStream == true {
153154
let components = dataString
@@ -169,31 +170,31 @@ extension ACMNetworking {
169170
onSuccess?(responseObject)
170171
}
171172
} catch let DecodingError.dataCorrupted(context) {
172-
let message = ACMStringUtils.shared.merge(list: [
173+
let message = endpoint.stringUtils?.merge(list: [
173174
context.debugDescription,
174175
])
175-
ACMBaseLogger.error(message)
176+
endpoint.logger?.error(message)
176177
} catch let DecodingError.keyNotFound(key, context) {
177-
let message = ACMStringUtils.shared.merge(list: [
178+
let message = endpoint.stringUtils?.merge(list: [
178179
"Key \(key) not found: \(context.debugDescription)",
179180
"codingPath: \(context.codingPath)",
180181
])
181-
ACMBaseLogger.error(message)
182+
endpoint.logger?.error(message)
182183
} catch let DecodingError.valueNotFound(value, context) {
183-
let message = ACMStringUtils.shared.merge(list: [
184+
let message = endpoint.stringUtils?.merge(list: [
184185
"Value \(value) not found: \(context.debugDescription)",
185186
"codingPath: \(context.codingPath)",
186187
])
187-
ACMBaseLogger.error(message)
188+
endpoint.logger?.error(message)
188189
} catch let DecodingError.typeMismatch(type, context) {
189-
let message = ACMStringUtils.shared.merge(list: [
190+
let message = endpoint.stringUtils?.merge(list: [
190191
"Type \(type) mismatch: \(context.debugDescription)",
191192
"codingPath: \(context.codingPath)",
192193
])
193-
ACMBaseLogger.error(message)
194+
endpoint.logger?.error(message)
194195
} catch let e {
195196
let errorMessage = String(format: ACMNetworkConstants.dataParseErrorMessage, e.localizedDescription)
196-
ACMBaseLogger.warning(errorMessage)
197+
endpoint.logger?.warning(errorMessage)
197198
onError?(ACMBaseNetworkError(message: ACMNetworkConstants.errorMessage, log: errorMessage, endpoint: endpoint))
198199
}
199200
}

Sources/ACMNetworking/Library/MainCalls/ACMNetworking+Download.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public extension ACMNetworking {
2626
{
2727
guard let urlRequest = generateURLRequest(endpoint: endpoint) else { return }
2828

29-
downloadTask = endpoint.session(delegate: self).downloadTask(with: urlRequest) { [weak self] url, urlResponse, error in
29+
session = endpoint.session(delegate: self)
30+
downloadTask = session?.downloadTask(with: urlRequest) { [weak self] url, urlResponse, error in
3031
guard let self else { return }
3132

3233
self.handleNilErrorResponse(with: endpoint, error: error, onError: onError)
@@ -43,8 +44,6 @@ public extension ACMNetworking {
4344
}
4445

4546
self.cancel()
46-
self.taskProgress?.invalidate()
47-
self.taskProgress = nil
4847

4948
do {
5049
let searchUrl = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
@@ -66,7 +65,7 @@ public extension ACMNetworking {
6665
onSuccess?(model)
6766
} catch let e {
6867
let errorMessage = String(format: ACMNetworkConstants.genericErrorMessage, e.localizedDescription)
69-
ACMBaseLogger.warning(errorMessage)
68+
endpoint.logger?.warning(errorMessage)
7069
onError?(ACMBaseNetworkError(message: ACMNetworkConstants.errorMessage, log: errorMessage, endpoint: endpoint))
7170
}
7271
}

0 commit comments

Comments
 (0)