Created
November 6, 2020 04:26
-
-
Save ryotapoi/2c869946eff9c962a4a088f5a7dc512c to your computer and use it in GitHub Desktop.
FileManagerによるファイル操作でCombineを使う。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Combine | |
extension FileManager { | |
struct RemoveItemPublisher: Publisher { | |
typealias Output = Void | |
typealias Failure = Error | |
var url: URL | |
var fileManager: FileManager | |
init(at url: URL, fileManager: FileManager) { | |
self.url = url | |
self.fileManager = fileManager | |
} | |
func receive<S>( | |
subscriber: S | |
) where S : Subscriber, Failure == S.Failure, Output == S.Input { | |
Deferred { | |
Future { [self] promise in | |
do { | |
try fileManager.removeItem(at: url) | |
promise(.success(())) | |
} catch { | |
promise(.failure(error)) | |
} | |
} | |
} | |
.receive(subscriber: subscriber) | |
} | |
func ignoreNoSuchFile() -> AnyPublisher<Void, Error> { | |
tryCatch { (error) -> AnyPublisher<Void, Error> in | |
let nserror = error as NSError | |
guard nserror.domain == NSCocoaErrorDomain, | |
CocoaError.Code(rawValue: nserror.code) == .fileNoSuchFile | |
else { | |
throw error | |
} | |
return Just(()).setFailureType(to: Error.self).eraseToAnyPublisher() | |
} | |
.eraseToAnyPublisher() | |
} | |
} | |
func removeItemPublisher(at url: URL) -> RemoveItemPublisher { | |
RemoveItemPublisher(at: url, fileManager: self) | |
} | |
func copyItemPublisher(at srcURL: URL, to dstURL: URL) -> AnyPublisher<Void, Error> { | |
Deferred { | |
Future { [self] promise in | |
do { | |
try copyItem(at: srcURL, to: dstURL) | |
promise(.success(())) | |
} catch { | |
promise(.failure(error)) | |
} | |
} | |
} | |
.eraseToAnyPublisher() | |
} | |
func mergeItemsPublisher(at srcURLs: [URL], to dstURL: URL) -> AnyPublisher<Void, Error> { | |
Deferred { | |
Future { promise in | |
do { | |
try Data().write(to: dstURL) | |
let fileHandle = try FileHandle(forWritingTo: dstURL) | |
try srcURLs | |
.map { try Data(contentsOf: $0, options: .mappedIfSafe) } | |
.forEach { fileHandle.write($0) } | |
try fileHandle.close() | |
promise(.success(())) | |
} catch { | |
promise(.failure(error)) | |
} | |
} | |
} | |
.eraseToAnyPublisher() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment