Summarizing the breakpoint continuation and practice _ios in the development of IOS

Source: Internet
Author: User
Tags tmp file

Objective

Summary of Breakpoint Continuation

The continuation of a breakpoint is the downloading or uploading of data from the place where the file was last interrupted, rather than starting with the file. (The text of the breakpoint is only related to download, upload is not discussed) when downloading large files, if you do not implement a breakpoint to continue the function, then each occurrence of abnormal or user active pause, will go to download, this is a waste of time. So in the project to achieve large file downloads, the breakpoint continues to pass the function is essential. Of course, there is a special situation in the continuation of the breakpoint, that is, the IOS application is killed by the user or the application of crash, to implement the application restart after the breakpoint continued transmission. This special situation is the problem to be solved in this paper.

The principle of continuous transmission of breakpoint

To implement a continuation of a breakpoint, the server must support it. Currently the most common are two ways:FTP and HTTP.

The following is a brief introduction to the principle of HTTP breakpoint continuation.

HTTP

Through HTTP, can be very convenient to achieve the continuation of the breakpoint. The continuation of a breakpoint is mainly dependent on the Range of the HTTP header definition. When requesting a range of resources, you can more efficiently make requests to large resources or recover downloads from transmission errors. With Range, the application can recover the download of a resource by using an HTTP request to retrieve a return or part of a failed resource. Of course not all servers support Range, but most servers are available. Range is calculated in bytes, and the request does not have to give a trailing byte number because the requester does not necessarily know the size of the resource.

The Range is defined as shown in Figure 1:

Figure 1. Http-range

Figure 2 shows the header information for HTTP request:

Figure 2. HTTP Request Example

In the example above, "range:bytes=1208765-" represents the portion of the requested resource after the beginning of 1208765 bytes.

Figure 3 shows the header information for the HTTP response:

Figure 3. HTTP Response Example

The "Accept-ranges:bytes" in the example above represents a range of server-side accepted request resources and allows byte-type access to the specified resource. " Content-Range: bytes 1208765-20489997/20489998 " indicates that the return provides the location within the original entity where the requested resource resides, and gives the length of the entire resource. The point to note here is that HTTP return code is 206 rather than 200.

Analysis of-afhttprequestoperation of breakpoint continuous transmission

After understanding the principle of the continuation of the break point, we can start to implement a breakpoint in the IOS application. Because the author project resources are deployed on the HTTP server, so the breakpoint continues to pass the function is based on HTTP implementation. First look at the implementation provided in the afnetworking of the third-party network framework. The Listing 1 sample code is the code used to implement the part of the breakpoint continuation:

Listing 1. Code to implement breakpoint continuation using Afhttprequestoperation

1 Specify download file address urlstring//2 Get saved file path FilePath//3 Create nsurlrequest nsurlrequest *request = [Nsurlrequest REQUESTW 
 Ithurl:[nsurl Urlwithstring:urlstring]]; 

 unsigned long long downloadedbytes = 0; if ([[[[[Nsfilemanager Defaultmanager] Fileexistsatpath:filepath]) {//3.1 if previously downloaded, add Range///Get SI for downloaded file in HTTP request header 

  Ze downloadedbytes = [self filesizeforpath:filepath]; Verify that the file is downloaded if (downloadedbytes > 0) {//if downloaded, the Range nsmutableurlrequest of the HTTP header part is modified when the breakpoint is renewed *mutableur 
    Lrequest = [request mutablecopy]; 
    NSString *requestrange = [NSString stringwithformat:@ "bytes=%llu-", downloadedbytes]; 
    [Mutableurlrequest setvalue:requestrange forhttpheaderfield:@ "Range"]; 
  request = Mutableurlrequest; }//4 create afhttprequestoperation afhttprequestoperation *operation = [[Afhttprequestoperation alloc] InitWithRe 

 Quest:request]; 5 Set the operation output stream, save in the 2nd step of the file Operation.outputstream = [Nsoutputstream Outputstreamtofileatpath:filepaTh append:yes]; 6 Setting download progress processing block [Operation setdownloadprogressblock:^ (Nsuinteger bytesread, Long long totalbytesread, long long to Talbytesexpectedtoread) {///Bytesread bytes currently read//totalbytesread read total bytes, including//totalbytesexpectedtoread file size before breakpoint continuation 

 Small}]; 7 Set success and failure processing block [Operation setcompletionblockwithsuccess:^ (Afhttprequestoperation *operation, id re 

 Sponseobject) {} failure:^ (afhttprequestoperation *operation, Nserror *error) {}]; 8 Start operation [Operation Start];

Using the above code, the extension of the breakpoint function is implemented, application restart or abnormal circumstances, can be based on the part of the download to start downloading. The key place is to persist the data that has already been downloaded. The next step is to see how afhttprequestoperation is implemented. By looking at the source, we found afhttprequestoperation inherited from afurlconnectionoperation , and afurlconnectionoperation implemented the nsurlconnectiondatadelegate protocol.

The processing process is shown in Figure 4:

Figure 4. Afurlhttprequestoperation processing Process

Here afnetworking why the threading asynchronous interface is adopted because the asynchronous interface is invoked directly on the main thread, and there is a runloop problem. When the main thread is called [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES] , the Listener task after the request is sent is added to the runloop of the main thread,runloopmode defaults to Nsdefaultrunloopmode, which indicates that only when the runloop of the frontline process N Sdefaultrunloopmode , this task will be executed. And when the user scrolling tableview and ScrollView, the main thread of the Runloop in nseventtrackingrunloop mode, it will not execute nsdefaultrunloopmode< /c10> 's mission.

In addition, the downloadprogressblock,success and failure blocks on this side need to be returned to the main thread because of the way the child threads invoke the interface.

The breakpoint continues to pass the actual combat

After you understand the principles and afhttprequestoperation examples, look at the three ways to achieve a continuation of a breakpoint:

Nsurlconnection

Based on Nsurlconnection, the key is to satisfy the Nsurlconnectiondatadelegate protocol, the following three methods are mainly realized:

Listing 2. The realization of nsurlconnection

 SWIFT//Request Failure processing func connection (connection:nsurlconnection, Didfailwitherror error:nserror) {Self.failureh Andler (Error:error)}//Received server response is called Func connection (connection:nsurlconnection, Didreceiveresponse Response:ns Urlresponse) {if self.totallength!= 0 {return} Self.writehandle = Nsfilehandle (forwritingatpath:fil 

  EManager.instance.cacheFilePath (self.filename!)) Self.totallength = Response.expectedcontentlength + self.currentlength}//When the server returns entity data is called Func connection (connection : Nsurlconnection, Didreceivedata data:nsdata) {Let length = data.length//move to the end of file Self.write Handle.seektoendoffile ()//write data to Sanbox self.writeHandle.writeData (data)//Calculate data length s Elf.currentlength = self.currentlength + length print ("Currentlength\ (self.currentlength)-totallength\" ( Self.totallength) ") if (Self.downloadprogresshandler!= nil) {self.downloadprogresshandler:Length, TotalBytes:self.currentLength, TotalBytesExpected:self.totalLength)}///call func after download connection  
  Didfinishloading (connection:nsurlconnection) {self.currentlength = 0 self.totallength = 0//close Write handle Self.writeHandle.closeFile () Self.writehandle = nil Let Cachefilepath = FileManager.instance.cacheFilePath (self 
  . filename!) 

  Let Documenfilepath = FileManager.instance.documentFilePath (self.filename!) 
    Do {try FileManager.instance.moveItemAtPath (Cachefilepath, Topath:documenfilepath)} catch let E as Nserror { 
 Print ("Error occurred when to move file: \ (E)")} Self.successhandler (responseobject:filename!) }

As shown in Figure 5, the general processing flow of the nsurlconnection is illustrated.

Figure 5. Nsurlconnection process

According to the general process in Figure 5, initialize Filehandler in didreceiveresponse , in didreceivedata , the file that will be received in the Connectio In Ndidfinishloading , empty the data and close the Filehandler, and save the file to the document directory. So when an exception is requested or the application is killed by the user, it is possible to continue the breakpoint by persisting the intermediate file. When initializing nsurlconnection, be aware that setting Scheduleinrunloop is Nsrunloopcommonmodes, or the progress bar UI cannot be updated.

The implementation effect is shown in Figure 6:

Figure 6. Nsurlconnection Demo

Nsurlsessiondatatask

Apple started in iOS7 with a new class nsurlsession, which has the nsurlconnection method and is more powerful. Due to the abandonment of the nsurlconnection from 2015 onwards, the reader recommends a continuation based on Nsurlsession. The mapping relationship between the nsurlconnection and Nsurlsession delegate methods, as shown in Figure 7. So the key is to meet Nsurlsessiondatadelegate and nsurlsessiontaskdelegate.

Figure 7. Mapping relationships between protocols

The code, as shown in Listing 3, is basically the same as the nsurlconnection implementation.

Listing 3. The realization of Nsurlsessiondatatask

 SWIFT 
 //Receive Data
 func urlsession (session:nsurlsession, Datatask:nsurlsessiondatatask, 
 idreceivedata Data:nsdata) { 
  //... 
 } 
 Receive server Response
 func urlsession (session:nsurlsession, Datatask:nsurlsessiondatatask, 
 didreceiveresponse Response:nsurlresponse, Completionhandler: 
 (nsurlsessionresponsedisposition)-> Void) { 
  //... 
  Completionhandler (. Allow) 
 } 

 //Request Complete
 func urlsession (session:nsurlsession, Task:nsurlsessiontask, 
 Didcompletewitherror error:nserror?) { 
  if error = = nil { 
    //... 
    Self.successhandler (responseobject:self.filename!) 
  } else { 
    Self.failurehandler (error:error!) 
  } 
 }

The difference in with Didcomletewitherror, it will be nsurlconnection in the connection:didfailwitherror:

and connectiondidfinishloading: integrated together, so this side should be based on error to distinguish between the execution of successful block and failed block.

The implementation effect is shown in Figure 8:

Figure 8. Nsurlsessiondatatask Demo

Nsurlsessiondowntask

Finally, look at the class Nsurlsessiondownloadtaskfor downloading in nsurlsession, the corresponding protocol is nsurlsessiondownloaddelegate, as shown in Figure 9:

Figure 9. Nsurlsessiondownloaddelegate protocol

After exiting Didfinishdownloadingtourl , the corresponding files in the temp directory are automatically deleted. So the file operation must be handled within this method. Before I wanted to find this TMP file, based on this file to do a continuation of the breakpoint, but has been unable to find the path to this file. After SWIFT announces Nsurlsession's source code, there may be a way to find it. Based on Nsurlsessiondownloadtask, you need to save the downloaded data in cancelbyproducingresumedata . Progress notice is very simple, directly in the URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite: implementation can be.

The code looks like listing 4:

Listing 4. The realization of Nsurlsessiondownloadtask

 SWIFT//ui triggers pause func pause () {Self.downloadtask? Cancelbyproducingresumedata ({data-> Void in if data!= nil {data!. WriteToFile (FileManager.instance.cacheFilePath (self.filename!), Atomically:false)}}) Self.downloadtask = Ni L//MARK:-nsurlsessiondownloaddelegate func urlsession (session:nsurlsession, Downloadtask:nsurlsessiondown Loadtask, Didwritedata Byteswritten:int64, Totalbyteswritten:int64, Totalbytesexpectedtowrite:int64) {if (self.do Wnloadprogresshandler!= Nil) {Self.downloadprogresshandler (Bytes:int (byteswritten), TOTALBYTES:TOTALBYTESWR Itten, Totalbytesexpected:totalbytesexpectedtowrite)}} func urlsession (Session:nsurlsession, Task:nsurlsessio Ntask, Didcompletewitherror error:nserror? 
  {if error!= nil {//real error self.failurehandler (error:error!) } func urlsession (Session:nsurlsession, Downloadtask:nsurlsessiondownloadtask, Didfinishdownloadingtourl Locati ON:nsurl) {Let Cachefilepath = FileManager.instance.cacheFilePath (self.filename!) 
  Let Documenfilepath = FileManager.instance.documentFilePath (self.filename!) Do {if FileManager.instance.fileExistsAtPath (cachefilepath) {try FileManager.instance.removeItemAtPath (Cachef Ilepath)} Try FileManager.instance.moveItemAtPath (location.path!, Topath:documenfilepath)} catch let E as  
 Nserror {print ("Error occurred when to move file: \ (E)")} Self.successhandler (Responseobject:documenfilepath) }

The implementation effect is shown in Figure 10:

Figure 10. Nsurlsessiondownloadtask Demo

Summarize

The above is the summary of the development of iOS in the end of the continuation of the breakpoint and practice of all content, in fact, the implementation of the download far more than these content, this article only introduced a simple use. Hope that in further study and application can continue to share with you. I hope this article can help everyone in need.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.