7

In Swift 2.0, how can I do the equivalent of @property (nonatomic, strong) NSManagedObject*<SomeProtocol> model?

Basically, I’m trying to define a property on my class that must both be a subclass of NSManagedObject AND conform to SomeProtocol (I will be calling methods defined by both).

I saw this: https://stackoverflow.com/a/25826948/363789, but I'm not sure how I can apply this syntax to property definition...

Community
  • 1
  • 1
elsurudo
  • 3,579
  • 2
  • 31
  • 48
  • Sorry, but I don't think your property declaration in Objective-C is legal. I find it only works with `id` – JeremyP Sep 07 '15 at 14:27
  • Hmm, you might be right. I suppose that's why there is an NSObject protocol. I wonder if Swift could simply auto-generate an accompanying protocol for each class? – elsurudo Sep 07 '15 at 14:55
  • If that's true, it kind of sucks, as it leads to some annoying casting being necessary – elsurudo Sep 07 '15 at 14:56
  • 1
    Can you just subclass NSManagedObject and make the subclass conform to your protocol? – JeremyP Sep 07 '15 at 14:58
  • Yeah, good workaround I suppose – elsurudo Sep 07 '15 at 15:01
  • Actually in my case it may not be possible (nicely), because I use mogenerator to generate the NSManagedObject subclasses, which my custom code then inherits from. – elsurudo Sep 07 '15 at 15:04

2 Answers2

5

Swift 4

This is now possible in Swift 4 using the following syntax:

var myObject: NSManagedObject & SomeProtocol
Marián Černý
  • 15,096
  • 4
  • 70
  • 83
2

Unfortunately Swift doesn't support such type composition yet.

Three reasonable good solutions as workaround (the third one is probably the best):

1. You can make another type with has those properties and all types have to inherit from it in order to be used as model.

class SomeManagedObject: NSManagedObject, SomeProtocol {
    // conforming to protocol
    func someMethod()
}

// type declaration
var model: SomeManagedObject

2. A more static way to solve this problem is to use generics:

class Aclass<T: NSManagedObject where T: SomeProtocol > {
    var model: T
}

Note: You don't have to care about another type which has to be the superclass but this solution is not as dynamic and abstract as the one before.

3. You could also make your own protocol and make NSManagedObject conform though an extension:

protocol ManagedProtocol {
    // if you want to access some methods/properties directly from the type
    func method()
    var variable: Int { get }

    // otherwise call all methods/properties through "managedObject"
    // this property also reduces casting if you want to have the object itself
    var managedObject: NSManagedObject { get }
}

extension NSManagedObject: ManagedProtocol {
    var managedObject: NSManagedObject { return self }
}

Now the type is abstract and can be written as:

var model: protocol<ManagedProtocol, SomeProtocol>
Qbyte
  • 12,753
  • 4
  • 41
  • 57