@@ -16,8 +16,8 @@ public class AlamofireWrapper: NSObject {
1616 private let requestsLock = NSLock ( )
1717
1818 // Interceptors
19- private var requestInterceptors : [ RequestInterceptor ] = [ ]
20- private var eventMonitors : [ EventMonitor ] = [ ]
19+ private var requestInterceptors : [ RequestInterceptorWrapper ] = [ ]
20+ private var eventMonitors : [ EventMonitorWrapper ] = [ ]
2121
2222 @objc public static let shared = AlamofireWrapper ( )
2323
@@ -82,31 +82,47 @@ public class AlamofireWrapper: NSObject {
8282 private func recreateSession( ) {
8383 let configuration = session. sessionConfiguration
8484
85+ // Cancel all active requests before recreating session
86+ requestsLock. lock ( )
87+ let requests = Array ( activeRequests. values)
88+ activeRequests. removeAll ( )
89+ requestsLock. unlock ( )
90+
91+ for request in requests {
92+ request. cancel ( )
93+ }
94+
8595 // Create a server trust manager with our security policy
8696 // Use allHostsMustBeEvaluated: false to allow default trust evaluation for non-pinned hosts
8797 let serverTrustManager = ServerTrustManager ( allHostsMustBeEvaluated: false , evaluators: [ : ] )
8898
8999 // Create new session with server trust manager and interceptors
90- // Keep the session alive by replacing it atomically
100+ // Store old session temporarily to ensure it doesn't get deallocated immediately
101+ let oldSession = session
91102 session = Session (
92103 configuration: configuration,
93104 serverTrustManager: serverTrustManager,
94105 eventMonitors: eventMonitors
95106 )
107+
108+ // Ensure old session is explicitly invalidated after new one is created
109+ DispatchQueue . global ( qos: . utility) . asyncAfter ( deadline: . now( ) + 0.5 ) {
110+ _ = oldSession // Keep reference until delayed closure executes
111+ }
96112 }
97113
98114 // MARK: - Interceptors
99115
100116 /// Add a request interceptor (for request/response modification)
101- // @objc public func addInterceptor(_ interceptor: RequestInterceptor ) {
102- // requestInterceptors.append(interceptor)
103- // }
117+ @objc public func addInterceptor( _ interceptor: RequestInterceptorWrapper ) {
118+ requestInterceptors. append ( interceptor)
119+ }
104120
105- // // / Add an event monitor (for network-level events like Android's network interceptor)
106- // @objc public func addEventMonitor(_ monitor: EventMonitor ) {
107- // eventMonitors.append(monitor)
108- // recreateSession() // Recreate session to apply new event monitors
109- // }
121+ /// Add an event monitor (for network-level events like Android's network interceptor)
122+ @objc public func addEventMonitor( _ monitor: EventMonitorWrapper ) {
123+ eventMonitors. append ( monitor)
124+ recreateSession ( ) // Recreate session to apply new event monitors
125+ }
110126
111127 // MARK: - Request Management
112128
@@ -1048,3 +1064,140 @@ public class ResponseSerializer: NSObject {
10481064 }
10491065 }
10501066}
1067+
1068+ // MARK: - Event Monitor Wrapper
1069+
1070+ /// Wrapper around Alamofire's EventMonitor protocol to make it accessible from Objective-C/NativeScript
1071+ @objc ( EventMonitorWrapper)
1072+ @objcMembers
1073+ public class EventMonitorWrapper : NSObject , EventMonitor {
1074+
1075+ // Callbacks that can be set from TypeScript
1076+ public var requestDidResumeCallback : ( ( URLRequest ) -> Void ) ?
1077+ public var requestDidSuspendCallback : ( ( URLRequest ) -> Void ) ?
1078+ public var requestDidCancelCallback : ( ( URLRequest ) -> Void ) ?
1079+ public var requestDidFinishCallback : ( ( URLRequest ) -> Void ) ?
1080+ public var requestDidCompleteCallback : ( ( URLRequest , HTTPURLResponse ? , Error ? ) -> Void ) ?
1081+ public var dataTaskDidReceiveDataCallback : ( ( URLRequest , Data ) -> Void ) ?
1082+
1083+ @objc public override init ( ) {
1084+ super. init ( )
1085+ }
1086+
1087+ // EventMonitor protocol implementation
1088+ public func request( _ request: Request , didCreateURLRequest urlRequest: URLRequest ) {
1089+ // No-op for now, can be added if needed
1090+ }
1091+
1092+ public func urlSession( _ session: URLSession , task: URLSessionTask , didCompleteWithError error: Error ? ) {
1093+ if let urlRequest = task. originalRequest {
1094+ requestDidCompleteCallback ? ( urlRequest, task. response as? HTTPURLResponse , error)
1095+ }
1096+ }
1097+
1098+ public func urlSession( _ session: URLSession , dataTask: URLSessionDataTask , didReceive data: Data ) {
1099+ if let urlRequest = dataTask. originalRequest {
1100+ dataTaskDidReceiveDataCallback ? ( urlRequest, data)
1101+ }
1102+ }
1103+
1104+ public func request( _ request: Request , didResumeTask task: URLSessionTask ) {
1105+ if let urlRequest = task. originalRequest {
1106+ requestDidResumeCallback ? ( urlRequest)
1107+ }
1108+ }
1109+
1110+ public func request( _ request: Request , didSuspendTask task: URLSessionTask ) {
1111+ if let urlRequest = task. originalRequest {
1112+ requestDidSuspendCallback ? ( urlRequest)
1113+ }
1114+ }
1115+
1116+ public func request( _ request: Request , didCancelTask task: URLSessionTask ) {
1117+ if let urlRequest = task. originalRequest {
1118+ requestDidCancelCallback ? ( urlRequest)
1119+ }
1120+ }
1121+
1122+ public func request( _ request: Request , didFinishTask task: URLSessionTask , with error: AFError ? ) {
1123+ if let urlRequest = task. originalRequest {
1124+ requestDidFinishCallback ? ( urlRequest)
1125+ }
1126+ }
1127+
1128+ // Setter methods for callbacks (called from TypeScript)
1129+ @objc public func setRequestDidResume( _ callback: @escaping ( URLRequest ) -> Void ) {
1130+ requestDidResumeCallback = callback
1131+ }
1132+
1133+ @objc public func setRequestDidSuspend( _ callback: @escaping ( URLRequest ) -> Void ) {
1134+ requestDidSuspendCallback = callback
1135+ }
1136+
1137+ @objc public func setRequestDidCancel( _ callback: @escaping ( URLRequest ) -> Void ) {
1138+ requestDidCancelCallback = callback
1139+ }
1140+
1141+ @objc public func setRequestDidFinish( _ callback: @escaping ( URLRequest ) -> Void ) {
1142+ requestDidFinishCallback = callback
1143+ }
1144+
1145+ @objc public func setRequestDidComplete( _ callback: @escaping ( URLRequest , HTTPURLResponse ? , Error ? ) -> Void ) {
1146+ requestDidCompleteCallback = callback
1147+ }
1148+
1149+ @objc public func setDataTaskDidReceiveData( _ callback: @escaping ( URLRequest , Data ) -> Void ) {
1150+ dataTaskDidReceiveDataCallback = callback
1151+ }
1152+ }
1153+
1154+ // MARK: - Request Interceptor Wrapper
1155+
1156+ /// Wrapper around Alamofire's RequestInterceptor protocol to make it accessible from Objective-C/NativeScript
1157+ @objc ( RequestInterceptorWrapper)
1158+ @objcMembers
1159+ public class RequestInterceptorWrapper : NSObject , RequestInterceptor {
1160+
1161+ // Callbacks that can be set from TypeScript
1162+ public var adaptCallback : ( ( URLRequest ) -> URLRequest ) ?
1163+ public var retryCallback : ( ( URLRequest , Error , Int ) -> Bool ) ?
1164+
1165+ @objc public override init ( ) {
1166+ super. init ( )
1167+ }
1168+
1169+ // RequestAdapter protocol
1170+ public func adapt( _ urlRequest: URLRequest , for session: Session , completion: @escaping ( Result < URLRequest , Error > ) -> Void ) {
1171+ if let adaptCallback = adaptCallback {
1172+ let adapted = adaptCallback ( urlRequest)
1173+ completion ( . success( adapted) )
1174+ } else {
1175+ completion ( . success( urlRequest) )
1176+ }
1177+ }
1178+
1179+ // RequestRetrier protocol
1180+ public func retry( _ request: Request , for session: Session , dueTo error: Error , completion: @escaping ( RetryResult ) -> Void ) {
1181+ guard let urlRequest = request. request else {
1182+ completion ( . doNotRetry)
1183+ return
1184+ }
1185+
1186+ if let retryCallback = retryCallback {
1187+ let retryCount = request. retryCount
1188+ let shouldRetry = retryCallback ( urlRequest, error, retryCount)
1189+ completion ( shouldRetry ? . retry : . doNotRetry)
1190+ } else {
1191+ completion ( . doNotRetry)
1192+ }
1193+ }
1194+
1195+ // Setter methods for callbacks (called from TypeScript)
1196+ @objc public func setAdapt( _ callback: @escaping ( URLRequest ) -> URLRequest ) {
1197+ adaptCallback = callback
1198+ }
1199+
1200+ @objc public func setRetry( _ callback: @escaping ( URLRequest , Error , Int ) -> Bool ) {
1201+ retryCallback = callback
1202+ }
1203+ }
0 commit comments