Reputation: 911
I'm working on a text editor and am having trouble with string optionals. I want to use a textView's string method; since it's an optional, Xcode insists that I unwrap it. When I use forced unwrapping (which is what Xcode recommends) I get runtime errors; I'd prefer to use optional chaining so that nil values don't cause a crash. But I can't get optional chaining to work.
To get open and save working, I'm trying to use self.textViewOne.string = self.text
in windowControllerDidLoadNib and self.text = self.textViewOne.string
in dataOfType. But I get crashes of "unexpectedly found nil while unwrapping an Optional value". Documentation tells me I should use if-let or even if-var to do this properly, but I can't; when I try to add if-let or if-var, I get an "Expected pattern" error, probably because the self.text variable already exists - but I don't know how else to unwrap properly.
In dataOfType
I even tried to unwrap it with a kludgey regular if-then statement:
if ((self.textViewOne.string) != nil)
{
self.text = self.textViewOne.string
}
else
{
self.text = ""
}
but even that doesn't work: Xcode still insists on a ! after self.textViewOne.string, and with or without the ! I still get a "fatal error: unexpectedly found nil while unwrapping an Optional value".
EDIT: Here's the complete code for the Document class as it currently stands (including a bit of tinkering after the original post, but still getting the error):
import Cocoa
class Document: NSDocument {
@IBOutlet var textViewOne: NSTextView!
@IBOutlet var textViewTwo: NSTextView!
var text = ""
override init() {
super.init()
// Add your subclass-specific initialization here.
}
override func windowControllerDidLoadNib(aController: NSWindowController) {
// The window has loaded, and is ready to display.
// Take the text that we loaded earlier and display it in the text field
super.windowControllerDidLoadNib(aController)
self.textViewOne.string = self.text
}
override class func autosavesInPlace() -> Bool {
return true
}
override var windowNibName: String? {
// Returns the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this property and override -makeWindowControllers instead.
return "Document"
}
override func dataOfType(typeName: String?, error outError: NSErrorPointer) -> NSData? {
// Convert the contents of the text field into data, and return it
if (self.textViewOne == nil)
{
println ("self.textViewOne is nil.")
}
if let someText = self.textViewOne.string {
self.text = someText
} else {
self.text = ""
}
return self.text.dataUsingEncoding( NSUTF8StringEncoding, allowLossyConversion: false)
}
override func readFromData(data: NSData, ofType typeName: String?, error outError: NSErrorPointer) -> Bool {
// Attempt to load a string from the data; if it works, store it in self.text
if data.length > 0
{
let string = NSString( data: data, encoding: NSUTF8StringEncoding)
self.text = string!
}
else
{ self.text = "" }
return true
}
}
Upvotes: 0
Views: 946
Reputation: 42489
What about using an if let
to unwrap a non-nil value from self.textViewOne
?
if let someText = self.textViewOne.string {
self.text = someText
} else {
self.text = ""
}
Upvotes: 3