1

I have a UITableViewController loading its entries from Core Data via a NSFetchedResultsController. Like this:

let historyItem = fetchedResults.objectAtIndexPath(indexPath) as HistoryItem

historyItem has a title property defined like this:

@NSManaged var title: String

but somehow the core data has a nil value for title in some entries which causes EXC_BAD_ACCESS because title is not String?. This problem has been addressed at Check if property is set in Core Data? and the high-voted answer there suggests something like this:

    if let possibleTitle = historyItem.title as String? {
        NSLog("possibleTitle was set OK")
    } else {
        NSLog("possibleTitle was nil")
    }

but I just tried that and it still gave me EXC_BAD_ACCESS: Xcode screen grab

That same problem and solution is also mentioned at Swift - casting a nil core data string as an optional value and my earlier duplicate question Swift: handling an unexpected nil value, when variable is not optional but it doesn't work for me. I'm using Xcode 6.2 and iOS8.

Am I misunderstanding something, please? Should this approach work?

Community
  • 1
  • 1
emrys57
  • 6,679
  • 3
  • 39
  • 49
  • That is interesting. I can confirm that the `as String?` solution proposed in http://stackoverflow.com/a/25664102/1187415 does not work anymore with Xcode 6.2 (tested in iOS 8 Simulator). Changing the property type to an optional (the "Old answer" in http://stackoverflow.com/a/25664102/1187415) still works. – Martin R Mar 13 '15 at 12:03
  • This is also discussed in the developer forum: https://devforums.apple.com/message/995243#995243, https://devforums.apple.com/message/1110385#1110385 and the advice is to file a bug report. – Martin R Mar 13 '15 at 12:11
  • 1
    `item.valueForKey("title") as String?` as proposed in http://stackoverflow.com/a/27412036/1187415 works as well. – Martin R Mar 13 '15 at 12:16
  • Ah! Thank you, @martin-r ! I tried `item.valueForKey("title") as String?` and that works for me. But nothing else did. If you'd like to propose that as an answer, I would be glad to tick it. Thanks! – emrys57 Mar 13 '15 at 12:36
  • The solution "as String?" doesn't work every time. For a NSDate non optional nil in CoreData works only if I logged it in printf before. It doesn't make sense at all. – Ben Apr 22 '15 at 15:54

1 Answers1

2

I think you should make your title an optional if core data can return nil value for title

@NSManaged var title: String?

And test it without the cast

if let possibleTitle = historyItem.title{
    NSLog("possibleTitle was set OK")
} else {
    NSLog("possibleTitle was nil")
}
IxPaka
  • 1,990
  • 1
  • 16
  • 18
  • Agreed, Xcode's generated classes are dangerous in Swift, since Core Data can return nil even when the generated property is not optional. – Tom Harrington Mar 13 '15 at 16:24
  • Agree with Tom. It is advisable to update your generated Swift classes according to your "optional" settings in the data model. – Mundi Mar 13 '15 at 16:37
  • 1
    I'd probably go farther and say that they should all be optional in Swift, because Core Data doesn't enforce rules about required attribute values until you save changes. There's still a window where the value could legitimately be nil. – Tom Harrington Mar 13 '15 at 17:25
  • Should we also check the "optional" checkbox into the datamodel file? – Ben Apr 22 '15 at 15:25
  • @Ben Only if it's supposed to be optional. I don't know if this is the best approach, but if the property isn't supposed to be optional, I give it the `!` ending in Swift so it's an error if nil, and I can still check if it's nil. – sudo Jun 01 '16 at 20:49