· 6 years ago · Jan 27, 2020, 09:52 AM
1Exercise: concurrency & background operation
2Your task is to implement an application which:
3
4downloads a set of (large) images to the Documents directory in the background,
5reports the download progress to the user,
6upon downloading of an image, performs face detection using that image,
7reports the number of detected faces to the user.
8Requirements
9The user interface should be simple. It's enough to have a big text view used as a log window and a button to start the downloads.
10The downloads should be performed in the background, i.e. they should carry on if the application goes to the background state.
11During download, the app should report the progress of each file in the UI, e.g.:
12Downloading "filename.jpg", 37% done...
13When the download of an image file completes:
14if the app is in the foreground, begin face detection immediately,
15if the app is in the background, begin face detection when the app becomes active again.
16Face detection for each image should be performed in a separate background thread. The app should stay responsive at all times.
17Tips & tricks
18The focus of this exercise is concurrency and background operations. Therefore, this section presents HOWTOs for tasks not directly related to that.
19
20Interacting with user interface
21The user interface must always be manipulated from the main dispatch queue. To update the UI from different queues, you must add the code block to that queue explicitly:
22
23DispatchQueue.main.async {
24 // do something...
25}
26Downloading files
27The download should be performed using downloadTask objects of URLSession. To do this:
28
29Create an URLSession object, providing URLSessionConfiguration.background as the configuration (with a unique identifier), self as the delegate and OperationQueue.main as the operation queue.
30Create an URL object using the URL string.
31Use the downloadTask method of URLSession to create the download task.
32Call the resume() method of the download task object to start the download immediately.
33Since we are submitting self as the delegate, our class (probably the view controller) must conform to the URLSessionDownloadDelegate protocol. The delegate functions is where progress reporting and initialisation of further tasks should take place.
34
35Note: App Transport Security prevents using plain HTTP by default. To enable it, add the following items to the Custom iOS target properties:
36App Transport Security Settings dictionary,
37in that dictionary, an Allow Arbitrary Loads boolean item with the value set to YES.
38
39
40Reporting progress
41The download task will periodically inform its delegate (i.e. your view controller) about its progress using urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:). Use it to display the progress to the user.
42
43Handling completion
44When the download is complete when the app is in the foreground, the download task will call urlSession(_:downloadTask:didFinishDownloadingTo:). The supplied URL contains the path to the downloaded file in the temporary directory.
45
46The file should be copied from that directory immediately. To get the Documents directory, you can use the NSSearchPathForDirectoriesInDomains function:
47
48let docDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
49Append the destination file name to that path.
50
51In iOS, you use the FileManager class to interact with files:
52
53to get a shared instance of the default file manager:
54let fileManager = FileManager.default
55you can check if a file exists using the file manager's fileExists(atPath:) method
56to delete a file, use removeItem(atPath:)
57to copy a file, use copyItem(atPath:toPath:)
58File manipulation functions throw exceptions. The easiest way to deal with them is to use try? (which results in an optional) or try! (if you are sure what you're doing). More info on error handling
59If the download completes when the app is inactive, the application(_:handleEventsForBackgroundURLSession:completionHandler:) will be called instead. Handle that event appropriately as well.
60
61Resuming downloads
62If the download task was interrupted, it will call urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:) when it resumes.
63
64Detecting faces
65Face detection is provided out-of-the-box by the Core Image framework. To use it, assuming the image is stored in a CIImage object:
66
67Create a CIDetector object of type CIDetectorTypeFace, providing a dictionary with the following options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]. The context may be nil.
68Use the features(in:) method of the detector, providing the CIImage object, to perform the actual detection.
69If the image is stored as a UIImage object, you can use the CIImage(image:) initialiser to create the CIImage.
70
71Table View tips & tricks
72Always use the Table View data source methods to feed data to the table view. A (commented out) skeleton of these methods will be automatically generated when you create a subclass of UITableViewController.
73Use the reloadData() method to force a refresh on the Table View.
74Example images
75https://upload.wikimedia.org/wikipedia/commons/0/04/Dyck,_Anthony_van_-_Family_Portrait.jpg
76https://upload.wikimedia.org/wikipedia/commons/0/06/Master_of_Flémalle_-_Portrait_of_a_Fat_Man_-_Google_Art_Project_(331318).jpg
77https://upload.wikimedia.org/wikipedia/commons/c/ce/Petrus_Christus_-_Portrait_of_a_Young_Woman_-_Google_Art_Project.jpg
78https://upload.wikimedia.org/wikipedia/commons/3/36/Quentin_Matsys_-_A_Grotesque_old_woman.jpg
79https://upload.wikimedia.org/wikipedia/commons/c/c8/Valmy_Battle_painting.jpg
80Report
81Your app should report each event in the text field, along with the time elapsed since the beginning, e.g.:
82
830.000 started download of file 1
840.011 started download of file 2
85...
863.611 finished download of file 1
87...
88The following events should be logged:
89
90started downloads, along with file URL,
91after every subsequent 10% progress of every download is reached,
92finished downloads, along with the URL of the downloaded file in the temporary directory,
93file copied to documents directory, along with full path to image in documents directory,
94started face detection task,
95finished face detection task, along with the number of faces.
96The log should be generated for the application running in the foreground all the time, i.e. the face detection procedure should start right after a given download completes.