Reputation: 25
I have a class
ManagedObject:NSManagedObject
and some subclass
MOProject:ManagedObject
MOOrganization:ManagedObject
and so on
and in the ManagedObject
request(Router.Create(object: userInfo)).responseJSON(completionHandler: { (response) -> Void in
switch response.result {
case .Success(let result):
Mapper<self>().map(result)
completion(result: Result(success:"dd"))
case .Failure( _):
completion(result: Result(failure: Error.CacheNotExist))
}
})
Mapper<self>().map(result)
is error
I just want is as T:ManagedObject
if I init MOProject I want
Mapper< MOProject >().map(result)
if I init MOOrganization I want
Mapper< MOOrganization >().map(result)
Upvotes: 2
Views: 539
Reputation: 126117
The problem here is that you're trying to specialize a generic type based on dynamic information. Swift doesn't do that, at least not without help.
What you can put in the angle brackets that go with a generic type is different depending on where you're using it. If you're defining a new generic type (like class Foo<T>
or func bar<T>(t: T)
), the angle brackets contain type parameters — those are like variables you can use within the type definition. If you're using a generic type (like var a: Foo<Int>
or calling bar("some string")
, which implicitly a call to bar<String>
, the angle brackets have to contain valid type names. In other words, the definition of a generic type is the place where it's generic, and the use site is the place where it's specialized.
Furthermore, specialization can only happen at compile time. What you put in the angle brackets when using a generic type has to be a type name known to the compiler, not an expression that produces something only at run time.
So your problem with trying to call a class method on Mapper<self>
is twofold: first, self
is not a type name, and second, you want the place where you're putting self
to contain something dynamic.
You can still conditionally create a Mapper<MOProject>
or a Mapper<MOOrganization>
based on the runtime type of self
— you just have to do that dispatch yourself so that you can provide static types to the compiler. The simplest (if not most elegant) way to do that might be to switch on the type:
//...
case .Success(let result):
switch self {
case is MOProject:
Mapper<MOProject>().map(result)
completion(result: Result(success:"dd"))
case is MOOrganization:
Mapper<MOOrganization>().map(result)
completion(result: Result(success:"dd"))
}
case .Failure( _):
//...
(Warning: coded in SE mobile app, untested. But something along these lines should work...)
Upvotes: 2
Reputation: 1784
Based on your usage I assume you want to use Self
not self
in your expression. The first is a type, the second is a property.
“Every instance of a type has an implicit property called self, which is exactly equivalent to the instance itself. You use the self property to refer to the current instance within its own instance methods.”
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2 Prerelease).” iBooks.
However, I'm not sure it'll work to use Self where you are attempting to use it. I'm having trouble finding documentation on Self. You'll often see it in protocol definitions. I don't know if it's legal in the context of a struct or class.
UPDATE: I just tried to use Self
in a class and got a compiler error: "Self
is only available in a protocol or as the result of a method in a class;"
If you provide more context of the method where you are using Mapper I could maybe suggest a fix. Do you have a generic type variable you can use in that context?
Upvotes: 0