2

We have an app with a fairly broad Core Data model, with lots of custom subclasses implemented in Objective C, but which are also used by a growing fraction of the app that's written in Swift. (For what it's worth: we're building with Xcode 7.3.1 against iOS 9.3, and the Swift code is thus 2.2.)

There's a helper function written in Swift that looks like this:

extension NSManagedObject {
  func inContext<T: NSManagedObject>(moc: NSManagedObjectContext) -> T? {
    guard self.managedObjectContext != moc else {
      return (self as! T)
    }

    do {
      let obj = try moc.existingObjectWithID(self.objectID)
      return (obj as! T)  // <--- fails here
    }
    catch let error {
      return nil
    }
  }
}

This is called in a fair number of places where objects jump contexts. Calling code generally looks like this:

let result: ECFoo? = foo.inContext(managedObjectContext)

This works flawlessly in debug builds of the app. But with optimizations turned on, I'm running into a case where this call fails at the line I've marked, where the fetched object is being cast from NSManagedObject to the correct subclass. The stack trace starts with swift_dynamicCastObjCClassUnconditional, and the message that gets logged to the console is:

Could not cast value of type 'ECFoo_Foo_' (0x7fb857d2c250) to 'ECFoo_Foo_' (0x7fb857d2c250).

If I put a breakpoint on that line, what I'm attempting to do seems fine in the debugger console:

(lldb) po moc.existingObjectWithID(self.objectID) is ECFoo
true

This is deeply confusing, because it's clearly the same type on both sides here, and they both appear to be the dynamically generated subclass, rather than the formal class that it should be trying to cast to (based on inference of the calling code). I can only assume that there's some piece of information being optimized away that is necessary to make this work, but I'm not entirely sure how to fix it.

Sixten Otto
  • 14,816
  • 3
  • 48
  • 60
  • I don't know why your code fails, but have a look a the various answers to http://stackoverflow.com/questions/28233302/how-to-use-generic-types-to-get-object-with-same-type, perhaps you can adapt that to your needs. – Martin R Aug 23 '16 at 19:47
  • Interesting. My version doesn't use `Self`, but the issue I'm having sounds very much like the one discussed in Rob's answer to that question. Certainly worth trying that approach instead! – Sixten Otto Aug 23 '16 at 21:04
  • …and, nope. Same crash with that code. Which makes me thing that perhaps the compiler is trying to be clever about the type inference (or maybe replacing some of the code-level inference with runtime types?), and getting things wrong. – Sixten Otto Aug 23 '16 at 21:10

0 Answers0