Swift, Self from AnyObject

Can I get Self from AnyObject?

Let's take this example:

// Superclass
class ManagedObject {
  class func findByID(id: String) -> AnyObject? {
    let objects = objectsWithPredicate(NSPredicate(format: "id == %@", id))
    return objects.firstObject() // Returns AnyObject
  }
}

// Subclass
class User : ManagedObject {
  class func returnFirstSelf() -> Self? {
    return findById("1") // This doesn't work because it returns AnyObject, but I need Self.
  }
}

      

If not, the best alternative way is to make sure that when called, the User.returnFirstSelf()

compiler returns User

, and when called, UserSubclass.returnFirstSelf()

it returns UserSubclass

.

+3


source to share


2 answers


You can simply return User?

from your class function if it's an option:

public class func returnFirstSelf() -> User? {
    if let found = findByID("1") as? User {
        return found
    }
    return nil
}

      

There is currently no (I know) return Self?

using Swift as it stands. The problem is that it Self

has several ... "dynamic" meaning, separate from specific types, protocols, and even generics. A concrete example to demonstrate this: What if you have a class StudentUser

that extends User

? If you tried to implement it like this:

class func returnFirstSelf() -> Self? {
    if let found = findById("1") as? Self { // Note the check that 'found' is a 'Self'
        return found
    }
    return nil
}

      



Then you run into a compiler error because you cannot use Self

outside the result of a protocol or class method. And if you try to implement it like this:

class func returnFirstSelf() -> Self? {
    if let found = findById("1") as? User { // Note 'User' instead of 'Self'
        return found
    }
    return nil
}

      

Then you run the risk of Self

actually mean StudentUser

, and even if you hand over a check that requires found

how User

, it does not guarantee that it found

will be StudentUser

. This will happen in case it StudentUser

does not override the method to ensure that it as?

checks StudentUser

.

The critical flaw here , in my opinion, is that you cannot use a keyword required

for class methods, requiring subclasses to override them. This will allow the compiler to ensure that any subclasses override this method and provide an implementation that can guarantee type safety.

+4


source


Craig Otis's answer is in place. However, one option is to create a copy constructor. This may not work for a polling scenario where they inherit from an NSManagedObject, but it should work for non-managed objects.



required init(user: User) {
    super.init(user: User) // or super.init() if top of inheritance.
    self.name = user.name
    self.email = user.email
    // etc.
}

class func returnFirstSelf() -> Self? {
    if let found = findById("1") { // Note the check that 'found' is a 'Self'
        return self.init(copy: found as! User)
    }
    return nil
}

      

0


source







All Articles