14

how can i check if an property is set in an Core Data Object?

I load all my Core Data Objects in an Directory:

var formQuestions = [Questions]()

And my Core Data NSManagementObject is:

@NSManaged var noticeText: String

formQuestions[indexPath.row].noticeText

// load with:

var fetchRequest = NSFetchRequest(entityName: "Questions")
fetchRequest.predicate = NSPredicate(format: "forms = %@", currentForm!)
formQuestions = context.executeFetchRequest(fetchRequest, error: nil) as [Questions]

My property "noticeText" could be empty or not, so when i create my Core Data Object some values could be not set. (The property is set as optional in Core Data)

When i now try to proove if there is a value, it always brings me an "EXC_BAD_ACCESS...."

if(formQuestions[indexPath.row].noticeText.isEmpty == false)

I could set an empty String when i create my Core Data Object, but that should be not a good solution.

So how can i check if an (optinal) and not setted value exists?

Thanks in advance.

MattyG
  • 8,449
  • 6
  • 44
  • 48
derdida
  • 14,784
  • 16
  • 90
  • 139
  • `@NSManaged var noticeText: String` -- it isn't optional -- make it optional with ! or ? depending on what you want – Daij-Djan Sep 04 '14 at 09:17
  • 1
    Oh my fault. But ive done this with Editor->CreateNSManagedSublcass and there is no ? when i use "Optional" - but that is not my problem - i still dont know how to check if the property is set or not. – derdida Sep 04 '14 at 10:15

2 Answers2

29

Update for Xcode 7: This issue has been solved with Xcode 7 beta 2. Optional Core Data properties are now defined as optional properties in the managed object subclasses generated by Xcode. It is no longer necessary to edit the generated class definition.


(Previous answer:)

When creating the NSManagedObject subclasses, Xcode does not define optional properties for those attributes which are marked as "optional" in the Core Data model inspector. This looks like a bug to me.

As a workaround, you can cast the property to an optional (as String? in your case) and then test it with optional binding

if let notice = someManagedObject.noticeText as String? {
    println(notice)
} else {
    // property not set
}

In your case that would be

if let notice = formQuestions[indexPath.row].noticeText as String? {
    println(notice)
} else {
    // property not set
}

Update: As of Xcode 6.2, this solution does not work anymore and crashes with a EXC_BAD_ACCESS runtime exception (compare Swift: detecting an unexpected nil value in a non-optional at runtime: casting as optional fails)

The "Old answer" solution below still works.


(Old answer:)

As @Daij-Djan already stated in a comment, you have to define the property for an optional Core Data attribute as optional or implicitly unwrapped optional:

@NSManaged var noticeText: String? // optional
@NSManaged var noticeText: String! // implicitly unwrapped optional

Unfortunately, Xcode does not define the optional properties correctly when creating the NSManagedObject subclasses, which means that you have to re-apply the changes if you create the subclasses again after a model change.

Also this seems to be still undocumented, but both variants worked in my test case.

You can test the property with == nil:

if formQuestions[indexPath.row].noticeText == nil {
    // property not set
}

or with an optional assignment:

if let notice = formQuestions[indexPath.row].noticeText {
    println(notice)
} else {
    // property not set
}
Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • What's the difference between String and String! in this case? Why is it necessary implicitly unwrap it? Why not just leave it as String ? – cfischer Oct 05 '14 at 11:24
  • 1
    @cfisher: A String cannot be nil. - But I would recommend to file a bug report at Apple. Xcode should generate the correct code for optional properties. – Martin R Oct 05 '14 at 11:31
  • If the downvoter could please leave an explaining comment? I would be really interested if anything is wrong here, and fix the answer if necessary. – Martin R Nov 24 '14 at 13:56
  • On Xcode 7b5/b6 I only get optionals generated Xcode for the NSManagedObject subclass extension. – Matthieu Riegler Aug 25 '15 at 18:59
5

Your application is crashing because you try to access a not optional variable that is nil. This is not allowed in swift. To fix your problem just add in the NSManagedObject subclass a ? to made the property optional:

@objc class MyModel: NSManagedObject {
    @NSManaged var noticeText: String? // <-- add ? here
}

Then to test the property you can do like this :

if let aNoticeText = formQuestions[indexPath.row].noticeText? {
    // do something with noticeText
}
ant_one
  • 845
  • 11
  • 11