mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-22 11:03:21 -04:00
ScanOperation
Off load scan task to background thread, blazingly fast app launch speed
This commit is contained in:
parent
c1edab0f05
commit
c50c7e8c6e
@ -57,7 +57,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, OperationQueueDelegate {
|
||||
func applicationDidBecomeActive(application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: #selector(AppDelegate.recordActiveSession), userInfo: nil, repeats: false)
|
||||
ZimMultiReader.sharedInstance.scan()
|
||||
}
|
||||
|
||||
func applicationWillTerminate(application: UIApplication) {
|
||||
|
@ -56,6 +56,7 @@ class MainVC: UIViewController {
|
||||
|
||||
override func viewDidAppear(animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// showGetStarted()
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,8 @@ extension MainVC: LPTBarButtonItemDelegate, TableOfContentsDelegate, ZimMultiRea
|
||||
|
||||
// MARK: - ZimMultiReaderDelegate
|
||||
|
||||
func firstBookAdded(id: ZimID) {
|
||||
func firstBookAdded() {
|
||||
guard let id = ZimMultiReader.sharedInstance.readers.keys.first else {return}
|
||||
loadMainPage(id)
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,6 @@ class Network: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate, NSU
|
||||
let bookDownloadTask = book.downloadTask else {return}
|
||||
|
||||
context.performBlockAndWait { () -> Void in
|
||||
book.isLocal = true
|
||||
self.context.deleteObject(bookDownloadTask)
|
||||
}
|
||||
|
||||
|
@ -348,6 +348,7 @@
|
||||
<webView hidden="YES" opaque="NO" contentMode="scaleToFill" layoutMarginsFollowReadableWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hIy-lu-2F6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<dataDetectorType key="dataDetectorTypes"/>
|
||||
</webView>
|
||||
<visualEffectView hidden="YES" opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="r0g-Y2-P3v">
|
||||
<rect key="frame" x="0.0" y="600" width="600" height="390"/>
|
||||
|
@ -180,7 +180,7 @@
|
||||
97E609F11D103DED00EBCB9D /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97E609F01D103DED00EBCB9D /* NotificationCenter.framework */; };
|
||||
97E609F41D103DED00EBCB9D /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E609F31D103DED00EBCB9D /* TodayViewController.swift */; };
|
||||
97E609F71D103DED00EBCB9D /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97E609F51D103DED00EBCB9D /* MainInterface.storyboard */; };
|
||||
97E60A021D10423A00EBCB9D /* ShadowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E60A011D10423A00EBCB9D /* ShadowView.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 */; };
|
||||
97E891691CA976E90001CA32 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97E891681CA976E90001CA32 /* FileManager.swift */; };
|
||||
@ -432,7 +432,7 @@
|
||||
97E609F31D103DED00EBCB9D /* TodayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewController.swift; sourceTree = "<group>"; };
|
||||
97E609F61D103DED00EBCB9D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
|
||||
97E609F81D103DED00EBCB9D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
97E60A011D10423A00EBCB9D /* ShadowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowView.swift; sourceTree = "<group>"; };
|
||||
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; };
|
||||
97E850CA1D2DA5B300A9F688 /* About.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = About.html; path = Kiwix/HelpDocuments/About.html; sourceTree = SOURCE_ROOT; };
|
||||
97E891681CA976E90001CA32 /* FileManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FileManager.swift; path = Kiwix/FileManager.swift; sourceTree = "<group>"; };
|
||||
@ -702,7 +702,7 @@
|
||||
971A10281D022AD5007FC62C /* LTBarButtonItem.swift */,
|
||||
971A10291D022AD5007FC62C /* RefreshHUD.swift */,
|
||||
971A102A1D022AD5007FC62C /* SearchBar.swift */,
|
||||
97E60A011D10423A00EBCB9D /* ShadowView.swift */,
|
||||
97E60A011D10423A00EBCB9D /* ShadowViews.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@ -1580,7 +1580,7 @@
|
||||
971A106F1D022E62007FC62C /* DownloadProgress.swift in Sources */,
|
||||
971A102E1D022AD5007FC62C /* TableViewCells.swift in Sources */,
|
||||
971A105A1D022DAD007FC62C /* LibraryLocalTBVC.swift in Sources */,
|
||||
97E60A021D10423A00EBCB9D /* ShadowView.swift in Sources */,
|
||||
97E60A021D10423A00EBCB9D /* ShadowViews.swift in Sources */,
|
||||
9779A1CC1D34225E0071EFAB /* SearchOperation.swift in Sources */,
|
||||
971A10671D022E0A007FC62C /* MainVCDelegates.swift in Sources */,
|
||||
978C58981C1CD86E0077AE47 /* Book.swift in Sources */,
|
||||
|
@ -9,29 +9,13 @@
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Kiwix-iOS/Model/KiwixURLProtocol.swift"
|
||||
timestampString = "489951010.904281"
|
||||
filePath = "Kiwix/ZimMultiReader/ZimMultiReader.swift"
|
||||
timestampString = "490129771.550315"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "24"
|
||||
endingLineNumber = "24"
|
||||
landmarkName = "startLoading()"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Kiwix-iOS/Model/KiwixURLProtocol.swift"
|
||||
timestampString = "489951012.827944"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "38"
|
||||
endingLineNumber = "38"
|
||||
landmarkName = "startLoading()"
|
||||
startingLineNumber = "71"
|
||||
endingLineNumber = "71"
|
||||
landmarkName = "directoryMonitorDidObserveChange()"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
|
@ -14,8 +14,6 @@ import CoreData
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
class Book: NSManagedObject {
|
||||
|
||||
// MARK: - Add Book
|
||||
@ -95,6 +93,20 @@ class Book: NSManagedObject {
|
||||
return fetch(fetchRequest, type: Book.self, context: context) ?? [Book]()
|
||||
}
|
||||
|
||||
class func fetchLocal(context: NSManagedObjectContext) -> [ZimID: Book] {
|
||||
let fetchRequest = NSFetchRequest(entityName: "Book")
|
||||
let predicate = NSPredicate(format: "isLocal = true")
|
||||
fetchRequest.predicate = predicate
|
||||
let localBooks = fetch(fetchRequest, type: Book.self, context: context) ?? [Book]()
|
||||
|
||||
var books = [ZimID: Book]()
|
||||
for book in localBooks {
|
||||
guard let id = book.id else {continue}
|
||||
books[id] = book
|
||||
}
|
||||
return books
|
||||
}
|
||||
|
||||
class func fetch(id: String, context: NSManagedObjectContext) -> Book? {
|
||||
let fetchRequest = NSFetchRequest(entityName: "Book")
|
||||
fetchRequest.predicate = NSPredicate(format: "id = %@", id)
|
||||
|
@ -6,8 +6,150 @@
|
||||
// Copyright © 2016 Chris. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import CoreData
|
||||
import PSOperations
|
||||
|
||||
class ScanLocalBookOperation: NSObject {
|
||||
class ScanLocalBookOperation: Operation {
|
||||
private let context: NSManagedObjectContext
|
||||
private var firstBookAdded = false
|
||||
|
||||
private var lastZimFileURLSnapshot: Set<NSURL>
|
||||
private var currentZimFileURLSnapshot = Set<NSURL>()
|
||||
private let lastIndexFolderURLSnapshot: Set<NSURL>
|
||||
private var currentIndexFolderURLSnapshot = Set<NSURL>()
|
||||
|
||||
private var completionHandler: ((currentZimFileURLSnapshot: Set<NSURL>, currentIndexFolderURLSnapshot: Set<NSURL>, firstBookAdded: Bool) -> Void)
|
||||
|
||||
init(lastZimFileURLSnapshot: Set<NSURL>, lastIndexFolderURLSnapshot: Set<NSURL>,
|
||||
completionHandler: ((currentZimFileURLSnapshot: Set<NSURL>, currentIndexFolderURLSnapshot: Set<NSURL>, firstBookAdded: Bool) -> Void)) {
|
||||
self.context = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
||||
context.parentContext = NSManagedObjectContext.mainQueueContext
|
||||
context.mergePolicy = NSOverwriteMergePolicy
|
||||
|
||||
self.lastZimFileURLSnapshot = lastZimFileURLSnapshot
|
||||
self.lastIndexFolderURLSnapshot = lastIndexFolderURLSnapshot
|
||||
|
||||
self.completionHandler = completionHandler
|
||||
super.init()
|
||||
name = String(self)
|
||||
}
|
||||
|
||||
override func execute() {
|
||||
defer {finish()}
|
||||
|
||||
currentZimFileURLSnapshot = ScanLocalBookOperation.getCurrentZimFileURLsInDocDir()
|
||||
currentIndexFolderURLSnapshot = ScanLocalBookOperation.getCurrentIndexFolderURLsInDocDir()
|
||||
|
||||
let zimFileHasChanges = lastZimFileURLSnapshot != currentZimFileURLSnapshot
|
||||
let indexFolderHasDeletions = lastIndexFolderURLSnapshot.subtract(currentIndexFolderURLSnapshot).count > 0
|
||||
|
||||
guard zimFileHasChanges || indexFolderHasDeletions else {return}
|
||||
|
||||
if indexFolderHasDeletions {
|
||||
lastZimFileURLSnapshot.removeAll()
|
||||
}
|
||||
|
||||
updateReaders()
|
||||
updateCoreData()
|
||||
}
|
||||
|
||||
override func finished(errors: [NSError]) {
|
||||
context.performBlockAndWait {self.context.saveIfNeeded()}
|
||||
NSManagedObjectContext.mainQueueContext.performBlockAndWait {NSManagedObjectContext.mainQueueContext.saveIfNeeded()}
|
||||
NSOperationQueue.mainQueue().addOperationWithBlock {
|
||||
self.completionHandler(currentZimFileURLSnapshot: self.currentZimFileURLSnapshot,
|
||||
currentIndexFolderURLSnapshot: self.currentIndexFolderURLSnapshot, firstBookAdded: self.firstBookAdded)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateReaders() {
|
||||
let addedZimFileURLs = currentZimFileURLSnapshot.subtract(lastZimFileURLSnapshot)
|
||||
let removedZimFileURLs = lastZimFileURLSnapshot.subtract(currentZimFileURLSnapshot)
|
||||
|
||||
guard addedZimFileURLs.count > 0 || removedZimFileURLs.count > 0 else {return}
|
||||
ZimMultiReader.sharedInstance.removeReaders(removedZimFileURLs)
|
||||
ZimMultiReader.sharedInstance.addReaders(addedZimFileURLs)
|
||||
}
|
||||
|
||||
private func updateCoreData() {
|
||||
let localBooks = Book.fetchLocal(context)
|
||||
let zimReaderIDs = Set(ZimMultiReader.sharedInstance.readers.keys)
|
||||
let addedZimFileIDs = zimReaderIDs.subtract(Set(localBooks.keys))
|
||||
let removedZimFileIDs = Set(localBooks.keys).subtract(zimReaderIDs)
|
||||
|
||||
for id in removedZimFileIDs {
|
||||
guard let book = localBooks[id] else {continue}
|
||||
if let _ = book.meta4URL {
|
||||
book.isLocal = false
|
||||
} else {
|
||||
context.deleteObject(book)
|
||||
}
|
||||
}
|
||||
|
||||
for id in addedZimFileIDs {
|
||||
guard let reader = ZimMultiReader.sharedInstance.readers[id] else {return}
|
||||
let book: Book? = {
|
||||
let book = Book.fetch(id, context: NSManagedObjectContext.mainQueueContext)
|
||||
return book ?? Book.add(reader.metaData, context: NSManagedObjectContext.mainQueueContext)
|
||||
}()
|
||||
book?.isLocal = true
|
||||
book?.hasIndex = reader.hasIndex()
|
||||
book?.hasPic = !reader.fileURL.absoluteString.containsString("nopic")
|
||||
}
|
||||
|
||||
for (id, book) in localBooks {
|
||||
guard !context.deletedObjects.contains(book) else {continue}
|
||||
guard let reader = ZimMultiReader.sharedInstance.readers[id] else {return}
|
||||
book.hasIndex = reader.hasIndex()
|
||||
}
|
||||
|
||||
if localBooks.count == 0 && addedZimFileIDs.count == 1 {
|
||||
firstBookAdded = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private class func getCurrentZimFileURLsInDocDir() -> Set<NSURL> {
|
||||
let fileURLs = FileManager.contentsOfDirectory(FileManager.docDirURL) ?? [NSURL]()
|
||||
var zimURLs = Set<NSURL>()
|
||||
for url in fileURLs {
|
||||
do {
|
||||
var isDirectory: AnyObject? = nil
|
||||
try url.getResourceValue(&isDirectory, forKey: NSURLIsDirectoryKey)
|
||||
if let isDirectory = (isDirectory as? NSNumber)?.boolValue {
|
||||
if !isDirectory {
|
||||
guard let pathExtension = url.pathExtension?.lowercaseString else {continue}
|
||||
guard pathExtension.containsString("zim") else {continue}
|
||||
zimURLs.insert(url)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return zimURLs
|
||||
}
|
||||
|
||||
private class func getCurrentIndexFolderURLsInDocDir() -> Set<NSURL> {
|
||||
let fileURLs = FileManager.contentsOfDirectory(FileManager.docDirURL) ?? [NSURL]()
|
||||
var folderURLs = Set<NSURL>()
|
||||
for url in fileURLs {
|
||||
do {
|
||||
var isDirectory: AnyObject? = nil
|
||||
try url.getResourceValue(&isDirectory, forKey: NSURLIsDirectoryKey)
|
||||
if let isDirectory = (isDirectory as? NSNumber)?.boolValue {
|
||||
if isDirectory {
|
||||
guard let pathExtension = url.pathExtension?.lowercaseString else {continue}
|
||||
guard pathExtension == "idx" else {continue}
|
||||
folderURLs.insert(url)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return folderURLs
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,26 +11,21 @@ import PSOperations
|
||||
|
||||
class ZimMultiReader: NSObject, DirectoryMonitorDelegate {
|
||||
static let sharedInstance = ZimMultiReader()
|
||||
let searchQueue = OperationQueue()
|
||||
|
||||
weak var delegate: ZimMultiReaderDelegate?
|
||||
private weak var scanOperation: ScanLocalBookOperation?
|
||||
|
||||
private(set) var readers = [ZimID: ZimReader]() {
|
||||
didSet {
|
||||
if readers.count == 1 {
|
||||
guard let id = readers.keys.first else {return}
|
||||
delegate?.firstBookAdded(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let searchQueue = OperationQueue()
|
||||
private(set) var isScanning = false
|
||||
private(set) var readers = [ZimID: ZimReader]()
|
||||
private let monitor = DirectoryMonitor(URL: FileManager.docDirURL)
|
||||
private var zimURLs = Set<NSURL>()
|
||||
private var zimAdded = Set<NSURL>()
|
||||
private var zimRemoved = Set<NSURL>()
|
||||
private var indexFolders = Set<NSURL>()
|
||||
private var lastZimFileURLSnapshot = Set<NSURL>()
|
||||
private var lastIndexFolderURLSnapshot = Set<NSURL>()
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
startScan()
|
||||
monitor.delegate = self
|
||||
monitor.startMonitoring()
|
||||
}
|
||||
@ -39,117 +34,54 @@ class ZimMultiReader: NSObject, DirectoryMonitorDelegate {
|
||||
monitor.stopMonitoring()
|
||||
}
|
||||
|
||||
// MARK: - DirectoryMonitorDelegate
|
||||
|
||||
func directoryMonitorDidObserveChange() {
|
||||
scan()
|
||||
}
|
||||
|
||||
// MARK: - Scan
|
||||
|
||||
func scan() {
|
||||
/*
|
||||
If list of idx folders changes, reinitialize all zim readers,
|
||||
because currently ZimMultiReader cannot find out which ZimReader's index folder is added or deleted
|
||||
|
||||
Note: when a idx folder is added, the content of that idx folder will not finish copying, which makes it meanless to detect idx folder addition.
|
||||
Because, with a incompletely copied idx folder, the xapian initializer is guranteed to fail. So here only check for idx folder deletion.
|
||||
If user added a idx folder, he or she needs to manaually call rescan.
|
||||
*/
|
||||
let newIndexFolders = Set(indexFolderURLsInDocDir)
|
||||
let deletedIdxFolder = indexFolders.subtract(newIndexFolders)
|
||||
|
||||
// Check for idx folder deletion
|
||||
if deletedIdxFolder.count > 0 {
|
||||
zimURLs.removeAll()
|
||||
}
|
||||
indexFolders = newIndexFolders
|
||||
|
||||
// Below are the lines required when not considering idx folders, aka only detect zim files
|
||||
let newZimURLs = Set(zimFileURLsInDocDir)
|
||||
zimAdded = newZimURLs.subtract(zimURLs)
|
||||
zimRemoved = zimURLs.subtract(newZimURLs)
|
||||
removeOld()
|
||||
addNew()
|
||||
zimAdded.removeAll()
|
||||
zimRemoved.removeAll()
|
||||
zimURLs = newZimURLs
|
||||
}
|
||||
|
||||
private func removeOld() {
|
||||
for (id, reader) in readers {
|
||||
guard zimRemoved.contains(reader.fileURL) else {continue}
|
||||
readers[id] = nil
|
||||
|
||||
guard let book = Book.fetch(id, context: NSManagedObjectContext.mainQueueContext) else {return}
|
||||
if let _ = book.meta4URL {
|
||||
book.isLocal = false
|
||||
} else {
|
||||
NSManagedObjectContext.mainQueueContext.deleteObject(book)
|
||||
func startScan() {
|
||||
isScanning = true
|
||||
let scanOperation = ScanLocalBookOperation(lastZimFileURLSnapshot: lastZimFileURLSnapshot, lastIndexFolderURLSnapshot: lastIndexFolderURLSnapshot) { (currentZimFileURLSnapshot, currentIndexFolderURLSnapshot, firstBookAdded) in
|
||||
self.lastZimFileURLSnapshot = currentZimFileURLSnapshot
|
||||
self.lastIndexFolderURLSnapshot = currentIndexFolderURLSnapshot
|
||||
self.isScanning = false
|
||||
if firstBookAdded {
|
||||
self.delegate?.firstBookAdded()
|
||||
}
|
||||
}
|
||||
GlobalOperationQueue.sharedInstance.addOperation(scanOperation)
|
||||
self.scanOperation = scanOperation
|
||||
}
|
||||
|
||||
private func addNew() {
|
||||
for url in zimAdded {
|
||||
// MARK: - Reader Addition / Deletion
|
||||
|
||||
func addReaders(urls: Set<NSURL>) {
|
||||
for url in urls {
|
||||
guard let reader = ZimReader(ZIMFileURL: url) else {continue}
|
||||
let id = reader.getID()
|
||||
readers[id] = reader
|
||||
|
||||
let book: Book? = {
|
||||
let book = Book.fetch(id, context: NSManagedObjectContext.mainQueueContext)
|
||||
return book ?? Book.add(reader.metaData, context: NSManagedObjectContext.mainQueueContext)
|
||||
}()
|
||||
book?.isLocal = true
|
||||
book?.hasIndex = reader.hasIndex()
|
||||
book?.hasPic = !reader.fileURL.absoluteString.containsString("nopic")
|
||||
}
|
||||
}
|
||||
|
||||
private var zimFileURLsInDocDir: [NSURL] {
|
||||
let fileURLs = FileManager.contentsOfDirectory(FileManager.docDirURL) ?? [NSURL]()
|
||||
var zimURLs = [NSURL]()
|
||||
for url in fileURLs {
|
||||
do {
|
||||
var isDirectory: AnyObject? = nil
|
||||
try url.getResourceValue(&isDirectory, forKey: NSURLIsDirectoryKey)
|
||||
if let isDirectory = (isDirectory as? NSNumber)?.boolValue {
|
||||
if !isDirectory {
|
||||
guard let pathExtension = url.pathExtension?.lowercaseString else {continue}
|
||||
guard pathExtension.containsString("zim") else {continue}
|
||||
zimURLs.append(url)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
func removeReaders(urls: Set<NSURL>) {
|
||||
for (id, reader) in readers {
|
||||
guard urls.contains(reader.fileURL) else {continue}
|
||||
readers[id] = nil
|
||||
}
|
||||
return zimURLs
|
||||
}
|
||||
|
||||
private var indexFolderURLsInDocDir: [NSURL] {
|
||||
let fileURLs = FileManager.contentsOfDirectory(FileManager.docDirURL) ?? [NSURL]()
|
||||
var folderURLs = [NSURL]()
|
||||
for url in fileURLs {
|
||||
do {
|
||||
var isDirectory: AnyObject? = nil
|
||||
try url.getResourceValue(&isDirectory, forKey: NSURLIsDirectoryKey)
|
||||
if let isDirectory = (isDirectory as? NSNumber)?.boolValue {
|
||||
if isDirectory {
|
||||
guard let pathExtension = url.pathExtension?.lowercaseString else {continue}
|
||||
guard pathExtension == "idx" else {continue}
|
||||
folderURLs.append(url)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return folderURLs
|
||||
// MARK: - DirectoryMonitorDelegate
|
||||
|
||||
func directoryMonitorDidObserveChange() {
|
||||
startScan()
|
||||
}
|
||||
|
||||
// MARK: - Search
|
||||
|
||||
func startSearch(searchOperation: SearchOperation) {
|
||||
if let scanOperation = scanOperation {
|
||||
searchOperation.addDependency(scanOperation)
|
||||
}
|
||||
searchQueue.addOperation(searchOperation)
|
||||
}
|
||||
|
||||
// MARK: Search (Old)
|
||||
|
||||
func search(searchTerm: String, zimFileID: String) -> [(id: String, articleTitle: String)] {
|
||||
var resultTuples = [(id: String, articleTitle: String)]()
|
||||
let firstCharRange = searchTerm.startIndex...searchTerm.startIndex
|
||||
@ -200,6 +132,6 @@ class ZimMultiReader: NSObject, DirectoryMonitorDelegate {
|
||||
}
|
||||
|
||||
protocol ZimMultiReaderDelegate: class {
|
||||
func firstBookAdded(id: ZimID)
|
||||
func firstBookAdded()
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user