@@ -32,7 +32,7 @@ @implementation GULNetworkURLSession {
32
32
#pragma clang diagnostic ignored "-Wunguarded-availability"
33
33
// / The session configuration. NSURLSessionConfiguration' is only available on iOS 7.0 or newer.
34
34
NSURLSessionConfiguration *_sessionConfig;
35
- #pragma pop
35
+ #pragma clang diagnostic pop
36
36
37
37
// / The path to the directory where all temporary files are stored before uploading.
38
38
NSURL *_networkDirectoryURL;
@@ -158,8 +158,7 @@ - (NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request
158
158
}
159
159
160
160
// Save the session into memory.
161
- NSMapTable *sessionIdentifierToFetcherMap = [[self class ] sessionIDToFetcherMap ];
162
- [sessionIdentifierToFetcherMap setObject: self forKey: _sessionID];
161
+ [self setSessionInFetcherMap: self forSessionID: _sessionID];
163
162
164
163
_request = [request copy ];
165
164
@@ -201,8 +200,7 @@ - (NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request
201
200
}
202
201
203
202
// Save the session into memory.
204
- NSMapTable *sessionIdentifierToFetcherMap = [[self class ] sessionIDToFetcherMap ];
205
- [sessionIdentifierToFetcherMap setObject: self forKey: _sessionID];
203
+ [self setSessionInFetcherMap: self forSessionID: _sessionID];
206
204
207
205
_request = [request copy ];
208
206
@@ -284,6 +282,17 @@ - (void)URLSession:(NSURLSession *)session
284
282
// Try to clean up stale files again.
285
283
[self maybeRemoveTempFilesAtURL: _networkDirectoryURL
286
284
expiringTime: kGULNetworkTempFolderExpireTime ];
285
+
286
+ // Invalidate the session only if it's owned by this class.
287
+ NSString *sessionID = session.configuration .identifier ;
288
+ if ([sessionID hasPrefix: kGULNetworkBackgroundSessionConfigIDPrefix ]) {
289
+ [session finishTasksAndInvalidate ];
290
+
291
+ // Explicitly remove the session so it won't be reused. The weak map table should
292
+ // remove the session on deallocation, but dealloc may not happen immediately after
293
+ // calling `finishTasksAndInvalidate`.
294
+ [self setSessionInFetcherMap: nil forSessionID: sessionID];
295
+ }
287
296
}
288
297
289
298
- (void )URLSession : (NSURLSession *)session
@@ -531,7 +540,8 @@ - (void)removeTempItemAtURL:(NSURL *)fileURL {
531
540
532
541
// / Gets the fetcher with the session ID.
533
542
+ (instancetype )fetcherWithSessionIdentifier : (NSString *)sessionIdentifier {
534
- NSMapTable *sessionIdentifierToFetcherMap = [self sessionIDToFetcherMap ];
543
+ NSMapTable <NSString *, GULNetworkURLSession *> *sessionIdentifierToFetcherMap =
544
+ [self sessionIDToFetcherMap ];
535
545
GULNetworkURLSession *session = [sessionIdentifierToFetcherMap objectForKey: sessionIdentifier];
536
546
if (!session && [sessionIdentifier hasPrefix: kGULNetworkBackgroundSessionConfigIDPrefix ]) {
537
547
session = [[GULNetworkURLSession alloc ] initWithNetworkLoggerDelegate: nil ];
@@ -542,7 +552,7 @@ + (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier {
542
552
}
543
553
544
554
// / Returns a map of the fetcher by session ID. Creates a map if it is not created.
545
- + (NSMapTable *)sessionIDToFetcherMap {
555
+ + (NSMapTable <NSString *, GULNetworkURLSession *> *)sessionIDToFetcherMap {
546
556
static NSMapTable *sessionIDToFetcherMap;
547
557
548
558
static dispatch_once_t sessionMapOnceToken;
@@ -651,6 +661,28 @@ - (void)URLSession:(NSURLSession *)session
651
661
652
662
#pragma mark - Helper Methods
653
663
664
+ - (void )setSessionInFetcherMap : (GULNetworkURLSession *)session forSessionID : (NSString *)sessionID {
665
+ GULNetworkURLSession *existingSession = [self sessionFromFetcherMapForSessionID: sessionID];
666
+ if (existingSession) {
667
+ // Invalidating doesn't seem like the right thing to do here since it may cancel an active
668
+ // background transfer if the background session is handling multiple requests. The old
669
+ // session will be dropped from the map table, but still complete its request.
670
+ NSString *message = [NSString stringWithFormat: @" Discarding session: %@ " , existingSession];
671
+ [_loggerDelegate GULNetwork_logWithLevel: kGULNetworkLogLevelInfo
672
+ messageCode: kGULNetworkMessageCodeURLSession019
673
+ message: message];
674
+ }
675
+ if (session) {
676
+ [[[self class ] sessionIDToFetcherMap ] setObject: session forKey: sessionID];
677
+ } else {
678
+ [[[self class ] sessionIDToFetcherMap ] removeObjectForKey: sessionID];
679
+ }
680
+ }
681
+
682
+ - (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID : (NSString *)sessionID {
683
+ return [[[self class ] sessionIDToFetcherMap ] objectForKey: sessionID];
684
+ }
685
+
654
686
- (void )callCompletionHandler : (GULNetworkURLSessionCompletionHandler)handler
655
687
withResponse : (NSHTTPURLResponse *)response
656
688
data : (NSData *)data
@@ -669,6 +701,7 @@ - (void)callCompletionHandler:(GULNetworkURLSessionCompletionHandler)handler
669
701
}
670
702
}
671
703
704
+ // Always use the request parameters even if the default session configuration is more restrictive.
672
705
- (void )populateSessionConfig : (NSURLSessionConfiguration *)sessionConfig
673
706
withRequest : (NSURLRequest *)request API_AVAILABLE(ios(7.0 )) {
674
707
sessionConfig.HTTPAdditionalHeaders = request.allHTTPHeaderFields ;
0 commit comments