mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-26 05:18:31 -04:00
DownloadBookOperation
This commit is contained in:
parent
e524c5325c
commit
710cbc50d7
@ -27,7 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
|
||||
NSURLProtocol.registerClass(KiwixURLProtocol)
|
||||
Network.shared.restoreProgresses()
|
||||
// Network.shared.restoreProgresses()
|
||||
|
||||
// Register notification
|
||||
let settings = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil) // Here are the notification permission the app wants
|
||||
@ -132,7 +132,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
}
|
||||
|
||||
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
|
||||
Network.shared.rejoinSessionWithIdentifier(identifier, completionHandler: completionHandler)
|
||||
// Network.shared.rejoinSessionWithIdentifier(identifier, completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
// MARK: Background Refresh
|
||||
|
@ -80,19 +80,23 @@ class BookDetailController: UITableViewController, CenterButtonCellDelegate, DZN
|
||||
|
||||
switch title {
|
||||
case Strings.downloadNow:
|
||||
func startDownload() {
|
||||
guard let bookID = book.id,
|
||||
let download = DownloadBookOperation(bookID: bookID) else {return}
|
||||
Network.shared.queue.addOperation(download)
|
||||
}
|
||||
|
||||
if book.spaceState == .Caution {
|
||||
let cancel = UIAlertAction(title: Strings.cancel, style: .Cancel, handler: nil)
|
||||
let download = UIAlertAction(title: Strings.SpaceAlert.downloadAnyway, style: .Destructive, handler: { (alert) in
|
||||
|
||||
startDownload()
|
||||
})
|
||||
let alertController = UIAlertController(title: Strings.SpaceAlert.spaceAlert, message: Strings.SpaceAlert.message, actions: [download, cancel])
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
} else {
|
||||
|
||||
startDownload()
|
||||
}
|
||||
// guard let download = DownloadBookOperation(book: book) else {return}
|
||||
// GlobalOperationQueue.sharedInstance.addOperation(download)
|
||||
default:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,7 @@ class DownloadTasksController: UITableViewController, NSFetchedResultsController
|
||||
}
|
||||
|
||||
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||
let cellIdentifier = "Cell"
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
|
||||
self.configureCell(cell, atIndexPath: indexPath)
|
||||
return cell
|
||||
}
|
||||
@ -60,9 +59,9 @@ class DownloadTasksController: UITableViewController, NSFetchedResultsController
|
||||
|
||||
cell.titleLabel.text = book.title
|
||||
cell.favIcon.image = UIImage(data: book.favIcon ?? NSData())
|
||||
|
||||
guard let progress = Network.shared.progresses[id] else {return}
|
||||
cell.progressView.progress = Float(progress.fractionCompleted)
|
||||
//
|
||||
// guard let progress = Network.shared.progresses[id] else {return}
|
||||
// cell.progressView.progress = Float(progress.fractionCompleted)
|
||||
|
||||
// switch downloadTask.state {
|
||||
// case .Queued, .Downloading:
|
||||
|
@ -49,7 +49,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.7.1326</string>
|
||||
<string>1.7.1353</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
@ -14,7 +14,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
weak var delegate: DownloadProgressReporting?
|
||||
|
||||
private let context = NSManagedObjectContext.mainQueueContext
|
||||
let operationQueue = OperationQueue()
|
||||
let queue = OperationQueue()
|
||||
|
||||
var progresses = [String: DownloadProgress]()
|
||||
private var timer: NSTimer?
|
||||
@ -30,7 +30,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
operationQueue.delegate = self
|
||||
queue.delegate = self
|
||||
}
|
||||
|
||||
func restoreProgresses() {
|
||||
@ -44,7 +44,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
let operation = URLSessionDownloadTaskOperation(downloadTask: task)
|
||||
operation.name = task.taskDescription
|
||||
operation.addObserver(NetworkObserver())
|
||||
self.operationQueue.addOperation(operation)
|
||||
self.queue.addOperation(operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,13 +77,13 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
|
||||
func pause(book: Book) {
|
||||
guard let id = book.id,
|
||||
let operation = operationQueue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
||||
let operation = queue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
||||
operation.cancel(produceResumeData: true)
|
||||
}
|
||||
|
||||
func cancel(book: Book) {
|
||||
guard let id = book.id,
|
||||
let operation = operationQueue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
||||
let operation = queue.getOperation(id) as? URLSessionDownloadTaskOperation else {return}
|
||||
operation.cancel(produceResumeData: false)
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
let operation = URLSessionDownloadTaskOperation(downloadTask: task)
|
||||
operation.name = id
|
||||
operation.addObserver(NetworkObserver())
|
||||
operationQueue.addOperation(operation)
|
||||
queue.addOperation(operation)
|
||||
|
||||
let progress = DownloadProgress(book: book)
|
||||
progress.downloadStarted(task)
|
||||
@ -107,7 +107,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
// MARK: - OperationQueueDelegate
|
||||
|
||||
func operationQueue(queue: OperationQueue, willAddOperation operation: NSOperation) {
|
||||
guard operationQueue.operationCount == 0 else {return}
|
||||
guard queue.operationCount == 0 else {return}
|
||||
shouldReportProgress = true
|
||||
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
|
||||
self.timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(Network.resetProgressReportingFlag), userInfo: nil, repeats: true)
|
||||
@ -117,7 +117,7 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
func operationQueue(queue: OperationQueue, willFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {}
|
||||
|
||||
func operationQueue(queue: OperationQueue, didFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {
|
||||
guard operationQueue.operationCount == 1 else {return}
|
||||
guard queue.operationCount == 1 else {return}
|
||||
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
|
||||
self.timer?.invalidate()
|
||||
self.shouldReportProgress = false
|
@ -21,7 +21,7 @@
|
||||
<rect key="frame" x="0.0" y="92" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="CVW-Rc-hA9" id="xiL-PL-4ko">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<frame key="frameInset" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="epH-ai-QrA">
|
||||
@ -219,21 +219,21 @@
|
||||
</view>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="RightDetailCell" textLabel="iyO-rf-lDN" detailTextLabel="iHv-oK-qrR" style="IBUITableViewCellStyleValue1" id="eB8-dt-BPR">
|
||||
<rect key="frame" x="0.0" y="185" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="184.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eB8-dt-BPR" id="KR4-kV-SZd">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<frame key="frameInset" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iyO-rf-lDN">
|
||||
<frame key="frameInset" minX="15" minY="12" width="32" height="20"/>
|
||||
<frame key="frameInset" minX="15" minY="12" width="31.5" height="19.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iHv-oK-qrR">
|
||||
<frame key="frameInset" minX="318" minY="12" width="42" height="20"/>
|
||||
<frame key="frameInset" minX="318.5" minY="12" width="41.5" height="19.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@ -243,10 +243,10 @@
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="CenterButtonCell" id="B0D-Hu-sVM" customClass="CenterButtonCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="229" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="228.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="B0D-Hu-sVM" id="Fhf-jb-Urf">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<frame key="frameInset" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TLs-eg-B0R">
|
||||
@ -268,10 +268,10 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="TextSwitchCell" id="c4v-9p-eEF" customClass="TextSwitchCell" customModule="Kiwix" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="273" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="272.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="c4v-9p-eEF" id="Lt6-0C-r4i">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<frame key="frameInset" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ksx-E1-lZ2">
|
||||
@ -295,14 +295,14 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="DescCell" textLabel="noJ-ab-bVV" style="IBUITableViewCellStyleDefault" id="J0v-iU-gZ5">
|
||||
<rect key="frame" x="0.0" y="317" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="316.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="J0v-iU-gZ5" id="bXv-ic-E7x">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<frame key="frameInset" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="noJ-ab-bVV">
|
||||
<frame key="frameInset" minX="15" width="345" height="43"/>
|
||||
<frame key="frameInset" minX="15" width="345" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
|
||||
<nil key="textColor"/>
|
||||
@ -362,7 +362,7 @@
|
||||
<rect key="frame" x="0.0" y="92" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nka-b0-ZmD" id="8e2-Je-FJO">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<frame key="frameInset" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oQE-dD-h38">
|
||||
@ -473,7 +473,7 @@
|
||||
<rect key="frame" x="0.0" y="92" width="375" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ekT-ed-PU9" id="oM4-Hy-Mkf">
|
||||
<frame key="frameInset" width="375" height="99"/>
|
||||
<frame key="frameInset" width="375" height="99.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" minimumFontSize="8" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hji-3G-yaJ">
|
||||
@ -514,7 +514,6 @@
|
||||
<outlet property="detailLabel" destination="v8H-ZV-HNV" id="nxi-1k-SWg"/>
|
||||
<outlet property="favIcon" destination="Too-68-SzG" id="nfU-AD-1Ji"/>
|
||||
<outlet property="progressView" destination="g0o-rT-qxm" id="Jaw-Zr-uJY"/>
|
||||
<outlet property="subtitleLabel" destination="v8H-ZV-HNV" id="sve-r0-ewd"/>
|
||||
<outlet property="titleLabel" destination="Hji-3G-yaJ" id="mZ2-S6-XEO"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
@ -580,21 +579,21 @@
|
||||
</view>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="qXz-1G-wA2" detailTextLabel="AMO-pu-z25" style="IBUITableViewCellStyleValue1" id="Zpf-Mi-m0A">
|
||||
<rect key="frame" x="0.0" y="110" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="109.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Zpf-Mi-m0A" id="S9T-Ce-Uax">
|
||||
<frame key="frameInset" width="375" height="43"/>
|
||||
<frame key="frameInset" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="qXz-1G-wA2">
|
||||
<frame key="frameInset" minX="15" minY="11" width="34" height="21"/>
|
||||
<frame key="frameInset" minX="15" minY="12" width="33.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="AMO-pu-z25">
|
||||
<frame key="frameInset" minX="316" minY="11" width="44" height="21"/>
|
||||
<frame key="frameInset" minX="316" minY="12" width="44" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.7.1570</string>
|
||||
<string>1.7.1627</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionMainStoryboard</key>
|
||||
|
@ -39,7 +39,6 @@
|
||||
971A104B1D022CBE007FC62C /* SearchBooksVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A10481D022CBE007FC62C /* SearchBooksVC.swift */; };
|
||||
971A10521D022D9D007FC62C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A10511D022D9D007FC62C /* AppDelegate.swift */; };
|
||||
971A106F1D022E62007FC62C /* DownloadProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A106D1D022E62007FC62C /* DownloadProgress.swift */; };
|
||||
971A10701D022E62007FC62C /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 971A106E1D022E62007FC62C /* Network.swift */; };
|
||||
971A10771D022F05007FC62C /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 971A10791D022F05007FC62C /* Localizable.stringsdict */; };
|
||||
971A107E1D022F74007FC62C /* DownloaderLearnMore.html in Resources */ = {isa = PBXBuildFile; fileRef = 971A107A1D022F74007FC62C /* DownloaderLearnMore.html */; };
|
||||
971A107F1D022F74007FC62C /* ImportBookLearnMore.html in Resources */ = {isa = PBXBuildFile; fileRef = 971A107B1D022F74007FC62C /* ImportBookLearnMore.html */; };
|
||||
@ -119,7 +118,6 @@
|
||||
97D681261D6F70AC00E5FA99 /* SearchOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D6811F1D6F70AC00E5FA99 /* SearchOperation.swift */; };
|
||||
97D681271D6F70AC00E5FA99 /* UIOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681201D6F70AC00E5FA99 /* UIOperations.swift */; };
|
||||
97D681281D6F70AC00E5FA99 /* UpdateWidgetDataSourceOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681211D6F70AC00E5FA99 /* UpdateWidgetDataSourceOperation.swift */; };
|
||||
97D681291D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681221D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift */; };
|
||||
97D6812E1D6F70DE00E5FA99 /* Kiwix.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812A1D6F70DE00E5FA99 /* Kiwix.xcdatamodeld */; };
|
||||
97D681311D6F70EC00E5FA99 /* 1.5.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */; };
|
||||
97D681321D6F70EC00E5FA99 /* MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */; };
|
||||
@ -134,6 +132,8 @@
|
||||
97D681441D6F713200E5FA99 /* CoreDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681431D6F713200E5FA99 /* CoreDataExtension.swift */; };
|
||||
97DB65DA1D4576B600A2CC42 /* BookmarkWidgetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DB65D91D4576B600A2CC42 /* BookmarkWidgetCell.swift */; };
|
||||
97DF259C1D6F7613001648A3 /* DownloadBookOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DF259B1D6F7612001648A3 /* DownloadBookOperation.swift */; };
|
||||
97DF259D1D6F9053001648A3 /* URLSessionDownloadTaskOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681221D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift */; };
|
||||
97DF25A01D6F996B001648A3 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DF259F1D6F996B001648A3 /* Network.swift */; };
|
||||
97E60A021D10423A00EBCB9D /* ShadowViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E60A011D10423A00EBCB9D /* ShadowViews.swift */; };
|
||||
97E60A061D10504000EBCB9D /* LibraryBackupTBVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E60A051D10504000EBCB9D /* LibraryBackupTBVC.swift */; };
|
||||
97E850CB1D2DA5B300A9F688 /* About.html in Resources */ = {isa = PBXBuildFile; fileRef = 97E850CA1D2DA5B300A9F688 /* About.html */; };
|
||||
@ -240,7 +240,7 @@
|
||||
971A10481D022CBE007FC62C /* SearchBooksVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SearchBooksVC.swift; path = "Kiwix-iOS/Controller/SearchBooksVC.swift"; sourceTree = SOURCE_ROOT; };
|
||||
971A10511D022D9D007FC62C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
971A106D1D022E62007FC62C /* DownloadProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DownloadProgress.swift; path = "Kiwix-iOS/Model/DownloadProgress.swift"; sourceTree = SOURCE_ROOT; };
|
||||
971A106E1D022E62007FC62C /* Network.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Network.swift; path = "Kiwix-iOS/Model/Network.swift"; sourceTree = SOURCE_ROOT; };
|
||||
971A106E1D022E62007FC62C /* Network_old.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Network_old.swift; path = "Kiwix-iOS/Model/Network_old.swift"; sourceTree = SOURCE_ROOT; };
|
||||
971A10781D022F05007FC62C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
971A107A1D022F74007FC62C /* DownloaderLearnMore.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = DownloaderLearnMore.html; path = Kiwix/HelpDocuments/DownloaderLearnMore.html; sourceTree = SOURCE_ROOT; };
|
||||
971A107B1D022F74007FC62C /* ImportBookLearnMore.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ImportBookLearnMore.html; path = Kiwix/HelpDocuments/ImportBookLearnMore.html; sourceTree = SOURCE_ROOT; };
|
||||
@ -358,6 +358,7 @@
|
||||
97D681431D6F713200E5FA99 /* CoreDataExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CoreDataExtension.swift; path = Classes/CoreDataExtension.swift; sourceTree = "<group>"; };
|
||||
97DB65D91D4576B600A2CC42 /* BookmarkWidgetCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkWidgetCell.swift; sourceTree = "<group>"; };
|
||||
97DF259B1D6F7612001648A3 /* DownloadBookOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadBookOperation.swift; sourceTree = "<group>"; };
|
||||
97DF259F1D6F996B001648A3 /* Network.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = "<group>"; };
|
||||
97E609F01D103DED00EBCB9D /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; };
|
||||
97E60A011D10423A00EBCB9D /* ShadowViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowViews.swift; sourceTree = "<group>"; };
|
||||
97E60A051D10504000EBCB9D /* LibraryBackupTBVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LibraryBackupTBVC.swift; path = "Kiwix-iOS/Controller/LibraryBackupTBVC.swift"; sourceTree = SOURCE_ROOT; };
|
||||
@ -570,7 +571,7 @@
|
||||
971904A41CA3204B002E9CFF /* Network */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
971A106E1D022E62007FC62C /* Network.swift */,
|
||||
971A106E1D022E62007FC62C /* Network_old.swift */,
|
||||
971A106D1D022E62007FC62C /* DownloadProgress.swift */,
|
||||
);
|
||||
name = Network;
|
||||
@ -665,6 +666,7 @@
|
||||
9711872D1CEB507600B9909D /* CoreData */,
|
||||
97163D321CD7E79F008BE2D6 /* Help Docs */,
|
||||
971187051CEB426E00B9909D /* libkiwix */,
|
||||
97DF259E1D6F9942001648A3 /* Network */,
|
||||
97E5712A1CA0525300FF4F1D /* Operation */,
|
||||
97A1FD3C1D6F728200A80EE2 /* Tools */,
|
||||
97BAA8EA1D3D2D0A0038F57F /* URLProtocol */,
|
||||
@ -944,6 +946,14 @@
|
||||
name = Reading;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97DF259E1D6F9942001648A3 /* Network */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97DF259F1D6F996B001648A3 /* Network.swift */,
|
||||
);
|
||||
path = Network;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97E108221C5D5A0D00E27FD3 /* Search */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1482,20 +1492,20 @@
|
||||
971A102C1D022AD5007FC62C /* BarButtonItems.swift in Sources */,
|
||||
971A10301D022AD5007FC62C /* LTBarButtonItem.swift in Sources */,
|
||||
971A103F1D022C42007FC62C /* LibraryAutoRefreshTBVC.swift in Sources */,
|
||||
97DF25A01D6F996B001648A3 /* Network.swift in Sources */,
|
||||
97A1FD391D6F724E00A80EE2 /* pathTools.cpp in Sources */,
|
||||
970E68B61D37E224001E8514 /* SettingSearchHistoryTBVC.swift in Sources */,
|
||||
97C005D81D64B99E004352E8 /* LibrarySplitViewController.swift in Sources */,
|
||||
97A7017F1D2C59CA00AAE2D8 /* GetStartedController.swift in Sources */,
|
||||
97A8AD871D6CF38000584ED1 /* EmptyTableConfigExtension.swift in Sources */,
|
||||
97D681291D6F70AC00E5FA99 /* URLSessionDownloadTaskOperation.swift in Sources */,
|
||||
97D452BC1D16FF010033666F /* RecentSearchCVC.swift in Sources */,
|
||||
971A106F1D022E62007FC62C /* DownloadProgress.swift in Sources */,
|
||||
971A102E1D022AD5007FC62C /* TableViewCells.swift in Sources */,
|
||||
97DF259D1D6F9053001648A3 /* URLSessionDownloadTaskOperation.swift in Sources */,
|
||||
97E60A021D10423A00EBCB9D /* ShadowViews.swift in Sources */,
|
||||
970E68BA1D3809A3001E8514 /* MainController.swift in Sources */,
|
||||
970C65501D398D5A007032F8 /* BookmarkControllerAnimator.swift in Sources */,
|
||||
97D6813A1D6F711A00E5FA99 /* Language.swift in Sources */,
|
||||
971A10701D022E62007FC62C /* Network.swift in Sources */,
|
||||
97D681401D6F712800E5FA99 /* Book+CoreDataProperties.swift in Sources */,
|
||||
97A1FD421D6F728200A80EE2 /* Extensions.swift in Sources */,
|
||||
97A1FD431D6F728200A80EE2 /* FileManager.swift in Sources */,
|
||||
|
40
Kiwix/Network/Network.swift
Normal file
40
Kiwix/Network/Network.swift
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Network.swift
|
||||
// Kiwix
|
||||
//
|
||||
// Created by Chris Li on 8/25/16.
|
||||
// Copyright © 2016 Chris. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Operations
|
||||
|
||||
// , NSURLSessionDownloadDelegate, NSURLSessionTaskDelegate
|
||||
class Network: NSObject, NSURLSessionDelegate, OperationQueueDelegate {
|
||||
static let shared = Network()
|
||||
let queue = OperationQueue()
|
||||
|
||||
private override init() {
|
||||
super.init()
|
||||
queue.delegate = self
|
||||
}
|
||||
|
||||
lazy var session: NSURLSession = {
|
||||
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("org.kiwix.www")
|
||||
configuration.allowsCellularAccess = false
|
||||
configuration.discretionary = false
|
||||
return NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
|
||||
}()
|
||||
|
||||
func operationQueue(queue: OperationQueue, willAddOperation operation: NSOperation) {
|
||||
print(queue.operationCount)
|
||||
}
|
||||
|
||||
func operationQueue(queue: OperationQueue, willFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {}
|
||||
|
||||
func operationQueue(queue: OperationQueue, didFinishOperation operation: NSOperation, withErrors errors: [ErrorType]) {
|
||||
print(queue.operationCount)
|
||||
}
|
||||
|
||||
func operationQueue(queue: OperationQueue, willProduceOperation operation: NSOperation) {}
|
||||
}
|
@ -10,34 +10,26 @@ import UIKit
|
||||
import CoreData
|
||||
import Operations
|
||||
|
||||
class DownloadBookOperation: Operation {
|
||||
class DownloadBookOperation: URLSessionDownloadTaskOperation {
|
||||
|
||||
private let bookID: String
|
||||
private let url: NSURL
|
||||
private let spaceState: BookSpaceState
|
||||
|
||||
init?(book: Book) {
|
||||
assert(NSThread.isMainThread(), "DownloadBookOperation has to be initialized on main thread")
|
||||
assert(book.managedObjectContext === NSManagedObjectContext.mainQueueContext, "DownloadBookOperation has to be initialized with a Book managed object belongs to the main queue context")
|
||||
self.bookID = book.id ?? ""
|
||||
self.url = book.url ?? NSURL()
|
||||
self.spaceState = book.spaceState
|
||||
convenience init?(bookID: String) {
|
||||
let context = NSManagedObjectContext.mainQueueContext
|
||||
guard let book = Book.fetch(bookID, context: context),
|
||||
let url = book.url else { return nil }
|
||||
|
||||
super.init()
|
||||
// book
|
||||
let task = Network.shared.session.downloadTaskWithURL(url)
|
||||
|
||||
if self.bookID == "" || self.url.absoluteString == "" {return nil}
|
||||
let downloadTask = DownloadTask.addOrUpdate(book, context: context)
|
||||
downloadTask?.state = .Queued
|
||||
|
||||
task.taskDescription = bookID
|
||||
self.init(downloadTask: task)
|
||||
}
|
||||
|
||||
override func execute() {
|
||||
defer { finish() }
|
||||
|
||||
switch spaceState {
|
||||
case .Caution:
|
||||
print("caution")
|
||||
case .NotEnough:
|
||||
print("not enough")
|
||||
default:
|
||||
print("down")
|
||||
}
|
||||
override func operationDidFinish(errors: [ErrorType]) {
|
||||
guard let bookID = task.taskDescription else {return}
|
||||
print("Book download op finished")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,20 +11,6 @@ import Operations
|
||||
|
||||
// MARK: - Alerts
|
||||
|
||||
class SpaceCautionAlert: AlertOperation<CloudBooksController> {
|
||||
let comment = "Library: Download Space Caution Alert"
|
||||
init(book: Book, presentationContext: CloudBooksController) {
|
||||
super.init(presentAlertFrom: presentationContext)
|
||||
|
||||
title = NSLocalizedString("Space Caution", comment: comment)
|
||||
message = NSLocalizedString("This book takes up more than 80% of the remaining space on your device. Are you sure you want to download it?", comment: comment)
|
||||
addActionWithTitle(NSLocalizedString("Download Anyway", comment: comment), style: .Default) { (alert) in
|
||||
Network.shared.download(book)
|
||||
}
|
||||
addActionWithTitle(LocalizedStrings.cancel)
|
||||
}
|
||||
}
|
||||
|
||||
class SpaceNotEnoughAlert: AlertOperation<CloudBooksController> {
|
||||
let comment = "Library: Download Space Not Enough Alert"
|
||||
init(book: Book, presentationContext: CloudBooksController) {
|
||||
|
@ -8,22 +8,26 @@
|
||||
|
||||
import Operations
|
||||
|
||||
private var URLSessionTaskOperationKVOContext = 0
|
||||
|
||||
public class URLSessionDownloadTaskOperation: Operation {
|
||||
let task: NSURLSessionDownloadTask
|
||||
private var produceResumeData = false
|
||||
private var observerRemoved = false
|
||||
private let stateLock = NSLock()
|
||||
class URLSessionDownloadTaskOperation: Operation {
|
||||
|
||||
public init(downloadTask: NSURLSessionDownloadTask) {
|
||||
enum KeyPath: String {
|
||||
case State = "state"
|
||||
}
|
||||
|
||||
let task: NSURLSessionTask
|
||||
|
||||
private var produceResumeData = false
|
||||
private var removedObserved = false
|
||||
private let lock = NSLock()
|
||||
|
||||
init(downloadTask: NSURLSessionDownloadTask) {
|
||||
self.task = downloadTask
|
||||
super.init()
|
||||
|
||||
addObserver(NetworkObserver())
|
||||
addObserver(DidCancelObserver { _ in
|
||||
if self.produceResumeData {
|
||||
downloadTask.cancelByProducingResumeData({ (data) in
|
||||
})
|
||||
downloadTask.cancelByProducingResumeData({ (data) in })
|
||||
} else {
|
||||
downloadTask.cancel()
|
||||
}
|
||||
@ -31,12 +35,12 @@ public class URLSessionDownloadTaskOperation: Operation {
|
||||
)
|
||||
}
|
||||
|
||||
public func cancel(produceResumeData produceResumeData: Bool) {
|
||||
func cancel(produceResumeData produceResumeData: Bool) {
|
||||
self.produceResumeData = produceResumeData
|
||||
cancel()
|
||||
}
|
||||
|
||||
override public func execute() {
|
||||
override func execute() {
|
||||
guard task.state == .Suspended || task.state == .Running else {
|
||||
finish()
|
||||
return
|
||||
@ -47,31 +51,37 @@ public class URLSessionDownloadTaskOperation: Operation {
|
||||
}
|
||||
}
|
||||
|
||||
override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
|
||||
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
|
||||
guard context == &URLSessionTaskOperationKVOContext else { return }
|
||||
|
||||
stateLock.withCriticalScope {
|
||||
if object === task && keyPath == "state" && !observerRemoved {
|
||||
lock.withCriticalScope {
|
||||
if object === task && keyPath == KeyPath.State.rawValue && !removedObserved {
|
||||
|
||||
if case .Completed = task.state {
|
||||
finish(task.error)
|
||||
}
|
||||
|
||||
switch task.state {
|
||||
case .Completed:
|
||||
finish()
|
||||
fallthrough
|
||||
case .Canceling:
|
||||
observerRemoved = true
|
||||
task.removeObserver(self, forKeyPath: "state")
|
||||
case .Completed, .Canceling:
|
||||
task.removeObserver(self, forKeyPath: KeyPath.State.rawValue)
|
||||
removedObserved = true
|
||||
default:
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension NSLock {
|
||||
func withCriticalScope<T>(@noescape block: Void -> T) -> T {
|
||||
// swiftlint:disable variable_name
|
||||
private var URLSessionTaskOperationKVOContext = 0
|
||||
// swiftlint:enable variable_name
|
||||
|
||||
extension NSLock {
|
||||
func withCriticalScope<T>(@noescape block: () -> T) -> T {
|
||||
lock()
|
||||
let value = block()
|
||||
unlock()
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user