Skip to content

Instantly share code, notes, and snippets.

@simplytunde
Last active August 29, 2015 14:12
Show Gist options
  • Save simplytunde/d600ba18426e474987a2 to your computer and use it in GitHub Desktop.
Save simplytunde/d600ba18426e474987a2 to your computer and use it in GitHub Desktop.
File Coordinator & Presenter

File Coordinator & Presenter

class FileManager:NSObject,NSFilePresenter { //You need to inherit for NSObject
    var fileUrl:NSURL?
    let operationQueue=NSOperationQueue()
    var contentToWrite=String() //This holds content
    var deleted=false //indicate if the file has been deleted
    var presentedItemURL: NSURL? {
        return fileUrl
    }
    var presentedItemOperationQueue: NSOperationQueue {
        return operationQueue
    }
    init(filePath: String) {
        fileUrl=NSURL(fileURLWithPath: filePath)
        super.init()
        NSFileCoordinator.addFilePresenter(self)
    }
    init(fileUrl:NSURL) {
        self.fileUrl=fileUrl
        super.init()
        NSFileCoordinator.addFilePresenter(self)
    }
    func write(content:String){
        contentToWrite+=content
    }
    func writeToFile(data: NSData)->Bool{
        if deleted{
            return false
        }
        let fileCordinator=NSFileCoordinator(filePresenter: nil)
        var error:NSError?
        var result=false
        fileCordinator.coordinateReadingItemAtURL(fileUrl!, options: NSFileCoordinatorReadingOptions.allZeros, writingItemAtURL: fileUrl!, options: NSFileCoordinatorWritingOptions.ForMerging, error: &error){
            (readUrl:NSURL!,writeUrl:NSURL!) -> Void in
            let fileHandle=NSFileHandle(forWritingToURL: writeUrl, error: &error)
            if error == nil{
                fileHandle?.seekToEndOfFile()
                fileHandle?.writeData(data)
                result=true
            }
        }
        return result
    }
    func writeToFile(content: String)->Bool{
        let data=content.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        return writeToFile(data!)
    }
    func readFromFile()->NSData?{
        var data:NSData?
        if fileUrl == nil || deleted{
            return data
        }
        var error:NSError?
        let fileCordinator=NSFileCoordinator(filePresenter: nil)
        fileCordinator.coordinateReadingItemAtURL(fileUrl!, options: NSFileCoordinatorReadingOptions.allZeros, error:&error){
            (readUrl:NSURL!) -> Void in
            data=NSData(contentsOfURL: readUrl)
        }
        return data
    }
    func readString()->String?{
        let data=readFromFile()
        if data != nil{
            return NSString(data: data!, encoding: NSUTF8StringEncoding)
        }
        return nil
    }
    func fileDeleted()->Bool{
        return deleted
    }
    func syncPrint(content:String){ // I had to use synchronized print because I notice println() wasnt synchronized
        objc_sync_enter(self)
        println(content)
        objc_sync_exit(self)
    }
    
    
    //Conform to NSFilePresenter
    
    
    func relinquishPresentedItemToReader(reader: ((() -> Void)!) -> Void) {
        if countElements(contentToWrite) > 0 && writeToFile(contentToWrite){
            contentToWrite=""
        }
        reader({
           //do something after reading is done
        })
        syncPrint("Reliquish file for reading")
    }
    func relinquishPresentedItemToWriter(writer: ((() -> Void)!) -> Void) {
        if countElements(contentToWrite) > 0 && writeToFile(contentToWrite){
            contentToWrite=""
        }
        writer({
             //do something after writer is done
        })
        syncPrint("Reliquish file for writing")
     }
    func savePresentedItemChangesWithCompletionHandler(completionHandler: (NSError!) -> Void) {
        if countElements(contentToWrite) > 0 && writeToFile(contentToWrite){
            contentToWrite=""
        }
        completionHandler(nil)
        syncPrint("Saved file")
    }
    func accommodatePresentedItemDeletionWithCompletionHandler(completionHandler: (NSError!) -> Void) {
        deleted=true
    }
    func presentedItemDidMoveToURL(newURL: NSURL) {
        fileUrl=newURL
    }
    func presentedItemDidGainVersion(version: NSFileVersion) {
        
    }
    func presentedItemDidLoseVersion(version: NSFileVersion) {
        
    }
    func presentedItemDidResolveConflictVersion(version: NSFileVersion) {
        
    }
    func presentedSubitemAtURL(oldURL: NSURL, didMoveToURL newURL: NSURL) {
        
    }
    func presentedSubitemAtURL(url: NSURL, didGainVersion version: NSFileVersion) {
        
    }
    func presentedSubitemAtURL(url: NSURL, didLoseVersion version: NSFileVersion) {
        
    }
    func presentedSubitemAtURL(url: NSURL, didResolveConflictVersion version: NSFileVersion) {
        
    }
    func accommodatePresentedSubitemDeletionAtURL(url: NSURL, completionHandler: (NSError!) -> Void) {
        completionHandler(nil)
    }
    func presentedSubitemDidChangeAtURL(url: NSURL) {
        
    }
    func presentedSubitemDidAppearAtURL(url: NSURL) {
        
    }
    deinit{
        writeToFile(contentToWrite) //Before the object is deallocated, write all to file
        NSFileCoordinator.removeFilePresenter(self)
    }
    //Comform to NSFilePresenter

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment