diff --git a/README.md b/README.md index fb8891d..db278cf 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,6 @@ This library provides implementaion of WebDav, Dropbox, OneDrive and SMB2 (incom All functions are async calls and it wont block your main thread. -Local and WebDAV providers are fully tested and can be used in production environment. - ## Features - [x] **LocalFileProvider** a wrapper around `FileManager` with some additions like searching and reading a portion of file. @@ -125,7 +123,7 @@ let documentsProvider = LocalFileProvider(sharedContainerId: "group.yourcompany. You can't change the base url later. and all paths are related to this base url by default. -To initialize an iCloud Container provider use below code, This will automatically manager creating Documents folder in container: +To initialize an iCloud Container provider look at [here](https://medium.com/ios-os-x-development/icloud-drive-documents-1a46b5706fe1) to see how to update project settings then use below code, This will automatically manager creating Documents folder in container: ```swift let documentsProvider = CloudFileProvider(containerId: nil) @@ -450,7 +448,9 @@ If you used this library in your project, you can open an issue to inform us. ## Meta -Amir-Abbas Mousavian – [@amosavian](https://twitter.com/amosavian) +Amir-Abbas Mousavian – [@amosavian](https://twitter.com/amosavian) + +Thanks to [Hootan Moradi](https://github.com/hoootan) for designing logo. Distributed under the MIT license. See `LICENSE` for more information. diff --git a/Sources/CloudFileProvider.swift b/Sources/CloudFileProvider.swift index 6631fcf..789cfea 100644 --- a/Sources/CloudFileProvider.swift +++ b/Sources/CloudFileProvider.swift @@ -18,6 +18,7 @@ open class CloudFileProvider: LocalFileProvider { return true } set { + assert(true, "CloudFileProvider.isCoorinating can't be set") return } } @@ -52,9 +53,9 @@ open class CloudFileProvider: LocalFileProvider { self.scope = scope let baseURL: URL if scope == .documents { - baseURL = ubiquityURL.standardized.appendingPathComponent("Documents/") + baseURL = ubiquityURL.appendingPathComponent("Documents/") } else { - baseURL = ubiquityURL.standardized + baseURL = ubiquityURL } super.init(baseURL: baseURL) @@ -107,11 +108,16 @@ open class CloudFileProvider: LocalFileProvider { } query.stop() - completionHandler(contents, nil) + self.dispatch_queue.async { + completionHandler(contents, nil) + } + }) DispatchQueue.main.async { if !query.start() { - completionHandler([], self.throwError(path, code: CocoaError.fileReadNoPermission)) + self.dispatch_queue.async { + completionHandler([], self.throwError(path, code: CocoaError.fileReadNoPermission)) + } } } } @@ -139,20 +145,28 @@ open class CloudFileProvider: LocalFileProvider { guard let result = (query.results as? [NSMetadataItem])?.first, let attribs = result.values(forAttributes: [NSMetadataItemURLKey, NSMetadataItemFSNameKey, NSMetadataItemPathKey, NSMetadataItemFSSizeKey, NSMetadataItemContentTypeTreeKey, NSMetadataItemFSCreationDateKey, NSMetadataItemFSContentChangeDateKey]) else { let error = self.throwError(path, code: CocoaError.fileNoSuchFile) - completionHandler(nil, error) + self.dispatch_queue.async { + completionHandler(nil, error) + } return } if let file = self.mapFileObject(attributes: attribs) { - completionHandler(file, nil) + self.dispatch_queue.async { + completionHandler(file, nil) + } } else { let noFileError = self.throwError(path, code: CocoaError.fileNoSuchFile) - completionHandler(nil, noFileError) + self.dispatch_queue.async { + completionHandler(nil, noFileError) + } } }) DispatchQueue.main.async { if !query.start() { - completionHandler(nil, self.throwError(path, code: CocoaError.fileReadNoPermission)) + self.dispatch_queue.async { + completionHandler(nil, self.throwError(path, code: CocoaError.fileReadNoPermission)) + } } } } @@ -322,13 +336,16 @@ open class CloudFileProvider: LocalFileProvider { contents.append(file) } } - - completionHandler(contents, nil) + self.dispatch_queue.async { + completionHandler(contents, nil) + } }) DispatchQueue.main.async { if !query.start() { - completionHandler([], self.throwError(path, code: CocoaError.fileReadNoPermission)) + self.dispatch_queue.async { + completionHandler([], self.throwError(path, code: CocoaError.fileReadNoPermission)) + } } } } @@ -422,9 +439,13 @@ open class CloudFileProvider: LocalFileProvider { do { var expiration: NSDate? let url = try self.opFileManager.url(forPublishingUbiquitousItemAt: self.url(of: path), expiration: &expiration) - completionHandler(url, nil, expiration as Date?, nil) + self.dispatch_queue.async { + completionHandler(url, nil, expiration as Date?, nil) + } } catch let e { - completionHandler(nil, nil, nil, e) + self.dispatch_queue.async { + completionHandler(nil, nil, nil, e) + } } } } diff --git a/Sources/FileObject.swift b/Sources/FileObject.swift index 5b88399..abad8e8 100644 --- a/Sources/FileObject.swift +++ b/Sources/FileObject.swift @@ -9,7 +9,7 @@ import Foundation /// Containts path and attributes of a file or resource. -open class FileObject { +open class FileObject: Equatable { /// A `Dictionary` contains file information, using `URLResourceKey` keys. open internal(set) var allValues: [URLResourceKey: Any] @@ -142,6 +142,16 @@ open class FileObject { open var isSymLink: Bool { return self.type == .symbolicLink } + + public static func ==(rhs: FileObject, lhs: FileObject) -> Bool { + if rhs === lhs { + return true + } + if let rurl = rhs.url, let lurl = lhs.url { + return rurl == lurl + } + return rhs.path == lhs.path && rhs.size == lhs.size && rhs.modifiedDate == lhs.modifiedDate + } } internal func resolve(dateString: String) -> Date? { diff --git a/fileprovider.png b/fileprovider.png index 9f294e8..9ee294e 100644 Binary files a/fileprovider.png and b/fileprovider.png differ