Originally created by @andriichernenko on GitHub (Oct 7, 2016).
Consider the following class hierarchy:
// abstract entity classopenclassStorableEntity:NSManagedObject,ImportableUniqueObject// ...openclassvaruniqueIDKeyPath:String{fatalError("this has to be overridden")}}// concrete entity@objc(Thing)classThing:StorableEntity{classvaruniqueIDKeyPath:String{return"id"}@NSManagedvarid:NSString@NSManagedvarcontent:String?}
Let's try to import a Thing now. The following code will work:
entityType is now StorableEntity.Type. Since importUniqueObject method relies on generic parameter to determine which type to use for static method calls this means that all invocations will be dispatched to StorableEntity instead of Thing. Which in this concrete example means that the app will crash because StorableEntity.uniqueIDKeyPath is abstract.
Originally created by @andriichernenko on GitHub (Oct 7, 2016).
Consider the following class hierarchy:
``` swift
// abstract entity class
open class StorableEntity: NSManagedObject, ImportableUniqueObject
// ...
open class var uniqueIDKeyPath: String {
fatalError("this has to be overridden")
}
}
// concrete entity
@objc(Thing)
class Thing: StorableEntity {
class var uniqueIDKeyPath: String {
return "id"
}
@NSManaged var id: NSString
@NSManaged var content: String?
}
```
Let's try to import a `Thing` now. The following code will work:
``` swift
let entityType = Thing.self
let object = try transaction.importUniqueObject(Into(entityType), source: ["id": "1", "content": "some content"])
```
but the following will not:
``` swift
let entityType: StorableEntity.Type = Thing.self
let object = try transaction.importUniqueObject(Into(entityType), source: ["id": "1", "content": "some content"])
```
`entityType` is now `StorableEntity.Type`. Since `importUniqueObject` method relies on generic parameter to determine which type to use for static method calls this means that all invocations will be dispatched to `StorableEntity` instead of `Thing`. Which in this concrete example means that the app will crash because `StorableEntity.uniqueIDKeyPath` is abstract.
Here's the project which reproduces this issue:
[CoreStoreImportCrasher.zip](https://github.com/JohnEstropia/CoreStore/files/516105/CoreStoreImportCrasher.zip)
I'm not sure if this is something to "fix". This is just how Swift generics works. If you really need dynamic behavior, Into clauses actually support that:
Use the initializer that accepts AnyClass argument. From clauses also support this.
@JohnEstropia commented on GitHub (Oct 7, 2016):
Hi, thank you for the feedback.
I'm not sure if this is something to "fix". This is just how Swift generics works. If you really need dynamic behavior, `Into` clauses actually support that:
``` swift
let object = try transaction.importUniqueObject(
Into<StorableEntity>(Thing.self as AnyClass),
source: ["id": "1", "content": "some content"]
)
```
Use the initializer that accepts `AnyClass` argument. `From` clauses also support this.
@andriichernenko commented on GitHub (Oct 7, 2016):
@JohnEstropia well, your example actually crashes as well. Have you tried running the test project?
This is just how Swift generics works.
yes, that's why generics cannot be relied on for correct method dispatch. I created pull request #108 which fixes this issue by calling type methods on entityClass from the Into object instead of calling them on the generic type. I'm not sure, however, if similar fixes are needed elsewhere.
@andriichernenko commented on GitHub (Oct 7, 2016):
@JohnEstropia well, your example actually crashes as well. Have you tried running the test project?
> This is just how Swift generics works.
yes, that's why generics cannot be relied on for correct method dispatch. I created pull request #108 which fixes this issue by calling type methods on `entityClass` from the `Into` object instead of calling them on the generic type. I'm not sure, however, if similar fixes are needed elsewhere.
Thanks for the PR! I'll check your project when I get access to Xcode later. Your PR looks good though, I'll look for other places similar.
@JohnEstropia commented on GitHub (Oct 7, 2016):
Thanks for the PR! I'll check your project when I get access to Xcode later. Your PR looks good though, I'll look for other places similar.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @andriichernenko on GitHub (Oct 7, 2016).
Consider the following class hierarchy:
Let's try to import a
Thingnow. The following code will work:but the following will not:
entityTypeis nowStorableEntity.Type. SinceimportUniqueObjectmethod relies on generic parameter to determine which type to use for static method calls this means that all invocations will be dispatched toStorableEntityinstead ofThing. Which in this concrete example means that the app will crash becauseStorableEntity.uniqueIDKeyPathis abstract.Here's the project which reproduces this issue:
CoreStoreImportCrasher.zip
@JohnEstropia commented on GitHub (Oct 7, 2016):
Hi, thank you for the feedback.
I'm not sure if this is something to "fix". This is just how Swift generics works. If you really need dynamic behavior,
Intoclauses actually support that:Use the initializer that accepts
AnyClassargument.Fromclauses also support this.@andriichernenko commented on GitHub (Oct 7, 2016):
@JohnEstropia well, your example actually crashes as well. Have you tried running the test project?
yes, that's why generics cannot be relied on for correct method dispatch. I created pull request #108 which fixes this issue by calling type methods on
entityClassfrom theIntoobject instead of calling them on the generic type. I'm not sure, however, if similar fixes are needed elsewhere.@JohnEstropia commented on GitHub (Oct 7, 2016):
Thanks for the PR! I'll check your project when I get access to Xcode later. Your PR looks good though, I'll look for other places similar.
@JohnEstropia commented on GitHub (Oct 8, 2016):
Merged your PR. Thanks again!
Will update the Swift 2.3 branch with the same fixes as well