๐๐๐Alamofire thematic directory. Welcome timely feedback and exchange
- Alamofire (1) – URLSession prerequisite skill
- Alamofire (2) — Background download
- Alamofire (3) — Request
- Alamofire (4) — Details you need to know
- Alamofire (5) — Response
- Alamofire (6) — Multiple form uploads
- Alamofire (7) — Safety certification
- Alamofire (8) — Final Chapter (Network Monitoring & Notifications & Downloader Packaging)
Alamofire Directory through train — Harmonious learning, not impatient!
This article mainly explains the background download, background download for the application, is a very important and relatively easy to use function. While it is true that background downloads can greatly improve the user experience, there are also a lot of pitfalls and confusion. The discussion will be carried out through URLSession and Alamofire respectively, so that the design thinking of Alamofire can be better understood by comparing learning. Alamofire continues to be updated, hope you hope!
URLSession handles background downloads
URLSession is relatively simple in terms of background processing.
// 1: initializes a background mode configuration
let configuration = URLSessionConfiguration.background(withIdentifier: self.createID())
// 2: Initializes the network download session through configuration
let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
// 3: session creates a downloadTask. - Resume Starts
session.downloadTask(with: url).resume()
Copy the code
- Initialize one
background
The pattern ofconfiguration
.configuration
There areThree models, onlybackground
Mode to carry out background download. - Initialize the network download session using configuration
session
, set up the related proxy, and call back the data signal response. session
createDownloadTask task
–resume
Start (Default:suspend
)- Then rely on the Apple-wrapped network processing, initiating the connection, sending the relevant request, and calling back the proxy response
//MARK: -session proxy
extension ViewController:URLSessionDownloadDelegate{
func urlSession(_ session: URLSession.downloadTask: URLSessionDownloadTask.didFinishDownloadingTo location: URL) {
// Download complete - Start sandbox migration
print("Download complete -\(location)")
let locationPath = location.path
// Copy to user directory (filename named after timestamp)
let documnets = NSHomeDirectory(a)+ "/Documents/" + self.lgCurrentDataTurnString() + ".mp4"
print("Mobile address:\(documnets)")
// Create file manager
let fileManager = FileManager.default
try! fileManager.moveItem(atPath: locationPath, toPath: documnets)
}
func urlSession(_ session: URLSession.downloadTask: URLSessionDownloadTask.didWriteData bytesWritten: Int64.totalBytesWritten: Int64.totalBytesExpectedToWrite: Int64) {
print(" bytesWritten \(bytesWritten)\n totalBytesWritten \(totalBytesWritten)\n totalBytesExpectedToWrite \(totalBytesExpectedToWrite)")
print("Download progress:\(Double(totalBytesWritten)/Double(totalBytesExpectedToWrite))\n")}}Copy the code
- To achieve the
URLSessionDownloadDelegate
thedidFinishDownloadingTo
Agent, download complete transfer of temporary file data to the corresponding sandbox save - through
urlSession(_ session: downloadTask:didWriteData bytesWritten: totalBytesWritten: totalBytesExpectedToWrite: )
The agent listens for download progress - This is also because
HTTP fragment transmission
Lead to the progress of a section of the feeling, in fact, to prove that the internal proxy method is constantly called, in order to progress callback!
The download function is implemented here, but there is still some way to go for the background download we need
Applications using an NSURLSession with a background configuration may be launched or resumed in the background in order to handle the completion of tasks in that session, or to handle authentication. This method will be called with the identifier of the session needing attention. Once a session has been created from a configuration object with that identifier, the session’s delegate will begin receiving callbacks. If such a session has already been created (if the app is being resumed, for instance), then the delegate will start receiving callbacks without any action by the application. You should call the completionHandler as soon as you’re finished handling the callbacks.
The Apple dad will always be able to give you good advice at the right time, and the ability to read documents will determine whether you stand on your toes in this era
class AppDelegate: UIResponder.UIApplicationDelegate {
var window: UIWindow?
// Used to save the completionHandler for the background download
var backgroundSessionCompletionHandler: (() -> Void)?
func application(_ application: UIApplication.handleEventsForBackgroundURLSession identifier: String.completionHandler: @escaping() - >Void) {
self.backgroundSessionCompletionHandler = completionHandler
}
}
Copy the code
- implementation
handleEventsForBackgroundURLSession
Can perfect background download - Tell the agent and
URLSession
Related events are waiting to be processed. - Application in all with
URLSession object
This method is called after the associated background transfer completes, whether the transfer completes successfully or causes an error. The application also calls this method if one or more transports require authentication. - Use this method to reconnect any
URLSession
And update the application’s user interface. For example, you can use this method to update progress indicators or merge new content into a view. After processing the event, incompletionHandler
Parameter to executeblock
So that the application can get a refresh of the user interface. - We’re through
handleEventsForBackgroundURLSession
Save the corresponding callback, this is also very necessary! Tell the system background download back to refresh the screen in time
inurlSessionDidFinishEvents
The proxy implementation is called
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
print("Background task download back")
DispatchQueue.main.async {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate.let backgroundHandle = appDelegate.backgroundSessionCompletionHandler else { return }
backgroundHandle()
}
}
Copy the code
- get
UIApplication.shared.delegate
The callback function executes - Note that the thread switches the main thread, after all, to refresh the interface
So what happens if you don’t implement the callback function in the proxy
- The ability to download in the background is not affected
- However, it will be very difficult to refresh the interface and affect the user experience
- At the same time, a warning will pop up at the printer’s desk
Warning: Application delegate received call to -
application:handleEventsForBackgroundURLSession:completionHandler:
but the completion handler was never called.
Copy the code
Second, Alamofire background download
The Alamofire framework has a nice feel to it. This rhythm is also a functional callback and supports chained requests and responses! The transaction logic is very clear, and the code readability is very concise
LGBackgroundManger.shared.manager
.download(self.urlDownloadStr) { (url, response) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
let documentUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let fileUrl = documentUrl?.appendingPathComponent(response.suggestedFilename!)
return (fileUrl!,[.removePreviousFile,.createIntermediateDirectories])
}
.response { (downloadResponse) in
print("Download callback information:\(downloadResponse)")
}
.downloadProgress { (progress) in
print("Download progress:\(progress)")}Copy the code
- This encapsulates a singleton
LGBackgroundManger
Background download management class, callmanger
Is also very direct. - Encapsulated thoughts no longer have to deal with disgusting agency events
struct LGBackgroundManger {
static let shared = LGBackgroundManger(a)let manager: SessionManager = {
let configuration = URLSessionConfiguration.background(withIdentifier: "com.lgcooci.AlamofireTest.demo")
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
configuration.timeoutIntervalForRequest = 10
configuration.timeoutIntervalForResource = 10
configuration.sharedContainerIdentifier = "group.com.lgcooci.AlamofireTest"
return SessionManager(configuration: configuration)
}()
}
Copy the code
Maybe a lot of students are questioning why we should make it simple profit, URLSession is not very good?
- If you are
SessionManager.defalut
Obviously not! After all, it requires a background download, so our sessionsession
The configuration of theURLSessionConfiguration
Is the requirement thatbackground
Patterns of - If you are not configured out of simple interest, or not held! When entering the background, it will be released, and the network will report an error:
Error Domain=NSURLErrorDomain Code=-999 "cancelled"
- The application layer can also be separated from the network layer.
- Can help in
AppDelegate
The callback is easy to receive directly
func application(_ application: UIApplication.handleEventsForBackgroundURLSession identifier: String.completionHandler: @escaping() - >Void) {
LGBackgroundManger.shared.manager.backgroundCompletionHandler = completionHandler
}
Copy the code
3. SessionManger process analysis
A good blog post, after all, has to explain the process behind such a clear code
1. SessionManger initialization
public init(
configuration: URLSessionConfiguration = URLSessionConfiguration.default,
delegate: SessionDelegate = SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = delegate
self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
Copy the code
- Initialize the
session
, includingconfiguration
ๆฏdefault
Mode, set up some basicSessionManager.defaultHTTPHeaders
Request header information - Proxy handover through creation
SessionDelegate
This is implemented by a class that specializes in handling agentsURLSession
The agent of
2. The agent completes the callback
SessionDelegate is a very important class that collects all agents
- URLSessionDelegate
- URLSessionTaskDelegate
- URLSessionDataDelegate
- URLSessionDownloadDelegate
- URLSessionStreamDelegate
We according to demand to urlSessionDidFinishEvents agent here
open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
sessionDidFinishEventsForBackgroundURLSession?(session)
}
Copy the code
- This is executed
sessionDidFinishEventsForBackgroundURLSession
Closure execution, so when is the closure declared? - And if you’re smart enough, you should be able to figure this out,
SessionDelegate
Just a specialized class that handles agents, but not logical data,According to the conventional ideas of packaging design will be delivered to the manager class.
In our SessionManger initialization, there is a way commonInit we see sessionDidFinishEventsForBackgroundURLSession below
delegate.sessionDidFinishEventsForBackgroundURLSession ={[weak self] session in
guard let strongSelf = self else { return }
DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?()}}Copy the code
- This is the proxy right here
delegate.sessionDidFinishEventsForBackgroundURLSession
Closure declaration - As soon as the background download is complete it will come inside the closure
- The main thread is called back
backgroundCompletionHandler
, it is also aSessionManger
External functions provided! You’re smart enough to know that I’m hereapplication
The essence of the operation!
3. Process summary
- First of all inAppDelegatethe
handleEventsForBackgroundURLSession
Method, passing the callback closureSessionManager ็backgroundCompletionHandler
- When the download is complete and comes backSessionDelegate ็
urlSessionDidFinishEvents
Invocation of proxy ->sessionDidFinishEventsForBackgroundURLSession
call - then
sessionDidFinishEventsForBackgroundURLSession
Perform – >SessionManager ็backgroundCompletionHandler
The implementation of the - Finally lead toAppDelegate ็
completionHandler
The call
Whether you use URLSession or Alamofire for background download, the principle is the same, but Alamofire is more dependent on sinking, network layer sinking, simpler to use, which is why we need third-party frameworks in many cases. You may have felt comfortable with Alamofire in this post, so if you like it, please pay attention. I will keep updating a series of Alamofire topics, thank you!
Just ask who else is there right now? 45 degrees up in the sky, damn it! My charm with no place to put it!