0

I did some Swift programming a while ago in Swift 2 and am now trying to use Swift 4. Maybe I'm missing something really obvious, but I cannot for the life of me get an extremely simple document-based text-editor application to open or save files properly. I make the document-based application and add this code to the ViewController class:

@IBOutlet var theTextView: NSTextView!

Then I go to the storyboard, add a Text View to it, and connect that Text View to theTextView as an outlet. I added data and read functions to Document as follows:

override func data(ofType typeName: String) throws -> Data {

    if let vc = self.windowControllers[0].contentViewController as? ViewController {
        return vc.theTextView.string.data(using: String.Encoding.utf8) ?? Data()
    }
    else {
        return Data()
    }

}

override func read(from data: Data, ofType typeName: String) throws {

    if let s = String(data: data, encoding: String.Encoding.utf8) {
        string = s
    }

    throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}

The program compiles and runs. But whenever I try to save, no save dialogue comes up and the app becomes unable to quit (I have to stop it from within Xcode). Whenever I try to open a file in the format I set for the app (even if it's just .txt), I get the error "The document [filename] could not be opened." I get that exact same behaviour even when all I do is add the TextView to the view controller, with no outlets or code added. So clearly Cocoa is not recognizing my code and/or outlets as relevant, but I cannot for the life of me figure out why. What am I missing?

Displaced Hoser
  • 871
  • 3
  • 13
  • 35
  • `data(ofType:)` just return the contents of the text view as `Data`, nothing else, and in the `read` method you are throwing the error in any case. By the way: A `String` created from UTF8 encoded `Data` and `Data` created from an UTF8 encoded `String` can never fail. Force unwrap the objects, the `if - let` expressions are pointless. – vadian Jul 10 '18 at 04:34
  • Getting rid of the "throws" seemed to fix the read method, thanks. I got rid of the optionals so the data function just contains `let vc = self.windowControllers[0].contentViewController as! ViewController` `return vc.theTextView.string.data(using: String.Encoding.utf8)!` and there's no chance of it returning just `Data` in the way there was before, but the same thing happens. – Displaced Hoser Jul 10 '18 at 14:13

1 Answers1

0

Getting rid of the "throw" above fixed the read method, as vadian suggested.

The data method required two fixes. First, apparently nobody tells you that you now need to set permissions to be able to write a file. I had to do that, following the instructions at the link.

Second, I think I needed to drop the "self" when getting the view controller? I'm not entirely sure why this worked, but I played around with the code more and changed it to

var viewController: ViewController? {
    return windowControllers[0].contentViewController as? ViewController
}

override func data(ofType typeName: String) throws -> Data {
    let textView = viewController?.theTextView
    if let contents = textView?.string.data(using: String.Encoding.utf8)
    {
        return contents
    }
    throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}

And that successfully saves.

Displaced Hoser
  • 871
  • 3
  • 13
  • 35