Check wifi is available on large file upload/download in iOS
The handleEventsForBackgroundURLSession Method
The purpose of the background transfer service is to allow large downloads or uploads to take place even when the associated application is placed in the background. In the situation where a transfer is in progress and the application is placed in the background, the handleEventsForBackgroundURLSession: delegate method of the application’s delegate class will be called and passed a reference to a completion handler which must be called by the application when the transfer is complete. The next step in this tutorial, therefore, is to implement this method and set up a property in which to store a reference to the completion handler. Begin by selecting the BackgroundTransferAppDelegate.h file adding a property for the completion handler reference as follows:
#import <UIKit/UIKit.h> @interface BackgroundTransferAppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (copy) void (^sessionCompletionHandler)(); @end
Next, edit the BackgroundTransferAppDelegate.m file and add the delegate method so that the completion handler reference is stored:
#import "BackgroundTransferAppDelegate.h" @implementation BackgroundTransferAppDelegate - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { self.sessionCompletionHandler = completionHandler; } . . . @end
Designing the User Interface
Select the Main.storyboard file and drag and drop an Image View object onto the canvas, resizing it to fill the entire view. With the image view selected in the canvas, select the Xcode Editor -> Resolve Auto Layout Issues -> Reset to Suggested Constraints menu option. This will add constraints attaching the image view to each side of the superview.
With the Image View object still selected, display the Attributes Inspector and change the Mode property to Aspect Fit. Display the Assistant Editor and ensure that it is displaying the content of the BackgroundTransferViewController.h file. Ctrl-click on the Image View in the canvas and drag the resulting line to a position just beneath the @interface line in the Assistant Editor panel. Release the line and establish an outlet for the image view named imageView.
With the BackgroundTransferViewController.h file still displayed, further modify the file to add properties to store the NSURLSession and NSURLSessionDownloadTask instances and to declare that the class implements a number of delegate protocols:
#import <UIKit/UIKit.h> @interface BackgroundTransferViewController : UIViewController <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate> @property (strong, nonatomic) IBOutlet UIImageView *imageView; @property (nonatomic) NSURLSession *session; @property (nonatomic) NSURLSessionDownloadTask *downloadTask; @end
Configuring the View Controller
The next step is to begin to implement the functionality in the view controller class. First, edit the file and import the App Delegate interface file (access to the app delegate instance will be needed later to access the reference to the completion handler) and declare the URL to the image file that is to be downloaded:
#import "BackgroundTransferViewController.h" #import "BackgroundTransferAppDelegate.h" static NSString *DownloadURLString = @"http://www.ebookfrenzy.com/code/LargeImage.jpg"; @interface BackgroundTransferViewController () @end @implementation BackgroundTransferViewController . . . @end
Next, edit the viewDidLoad method in the BackgroundTransferViewController.m file to begin the initialization process:
- (void)viewDidLoad { [super viewDidLoad]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.ebookfrenzy.transfer"]; configuration.allowsCellularAccess = YES; _session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURL *downloadURL = [NSURL URLWithString:DownloadURLString]; NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; _downloadTask = [self.session downloadTaskWithRequest:request]; [_downloadTask resume]; }
The above code begins by creating a new NSURLSessionConfiguration instance, configured to perform a background transfer and specifying a unique identifier for the session (in this case the package name of the application):
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.ebookfrenzy.transfer"]; configuration.allowsCellularAccess = YES;
By calling the backgroundSessionConfiguration method in the above code we are indicating that the session is required to perform file transfer related tasks. An option is also set to allow the transfer to use the cellular connection on the device if WiFi is not available. For large transfers, this should be set to NO, or the user given the opportunity to configure this setting to avoid incurring additional costs on their cellular data plan.
An NSURLSession instance is then created using the configuration object and designating the current class as the delegate for the session:
_session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
Next, an NSURL object is created containing the URL of the image file to be downloaded and an NSURLRequest object initialized with this URL:
NSURL *downloadURL = [NSURL URLWithString:DownloadURLString]; NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];
Finally, the download task request is created and resumed (tasks do not start at the point of creation and will not run until the resume method is called):
_downloadTask = [self.session downloadTaskWithRequest:request]; [_downloadTask resume];
All that remains is to implement the delegate methods.