Reputation: 16598
I'm developing a framework in Swift 2.0 that adds a few extension methods to NSManagedObjectContext
. These methods are useful but not required for use of the framework. I'd like users of my framework to be able to opt in to the use of these extension methods, perhaps by implementing a protocol. However, when I provide a default implementation, I want to be sure that self
is always NSManagedObjectContext
. How can I do this?
Upvotes: 1
Views: 161
Reputation: 16598
Most people are now aware that Swift 2.0 can specialize extension methods around generic parameters, e.g.,
extension Array where T: Int {
// This method only appears when T is an Int
func seven() -> Int {
return 7
}
}
It's also possible to constrain Self
in this way, and this is what makes "opt-in" extension methods possible. The key here is where Self: NSManagedObjectContext
in the extension below:
public protocol ManagedObjectContextType {
func from<E: EntityType>(_: E.Type) -> EntityQuery<E>
func newEntity<E: NSManagedObject where E: EntityType>(_: E.Type) -> E
func newEntity<E: NSManagedObject where E: EntityType>() -> E
}
/**
Extend `NSManagedObjectContext` with this interface in your project to
benefit from these methods.
*/
extension ManagedObjectContextType where Self: NSManagedObjectContext {
/**
Initiates a query whose result type is `E`.
*/
public func from<E: EntityType>(_: E.Type) -> EntityQuery<E> {
return EntityQuery(builder: QueryBuilder()).context(self)
}
/**
Inserts a newly allocated entity of type `E` into this `NSManagedObjectContext`.
*/
public func newEntity<E: NSManagedObject where E: EntityType>(_: E.Type) -> E {
return NSEntityDescription.insertNewObjectForEntityForName(E.entityNameInManagedObjectModel(persistentStoreCoordinator!.managedObjectModel), inManagedObjectContext: self) as! E
}
/**
Inserts a newly allocated entity of type `E` into this `NSManagedObjectContext`.
*/
public func newEntity<E: NSManagedObject where E: EntityType>() -> E {
return newEntity(E)
}
}
The beauty of this is that the Swift 2.0 compiler recognizes in these extensions that self
is an instance of NSManagedObjectContext
, so you can use all of the appropriate methods.
Now, users of your framework can decide for themselves whether they want to add your extension methods by simply implementing the interface in their project:
extension NSManagedObjectContext: ManagedObjectContextType {}
This allows authors of frameworks to provide extensions and default implementations in a less cluttered way.
Upvotes: 2