3

In Objective-C I had a category:

@implementation NSObject (Entity)
+ (instancetype)entity{
    Class cl = self.class;
    NSObject *obj = [[cl alloc] init];

    return obj;
}
@end

Let's assume there are classes A and B:

@interface A : NSObject
@end

@interface B : NSObject
@end

And then I can use static entity method to create objects like:

NSObject *o = [NSObject entity]; // type of NSObject
A *a = [A entity];               // type of A
B *b = [B entity];               // type of B

How can I write that category in Swift? I know it's possible to create an object by knowing the type like let s = NSString.self; var str = s.init(), but here I don't know the class, that should be something like self.self which has no sense and doesn't work for sure.

Thanks in advance

1
  • This question is at least similar to yours. Commented Sep 21, 2015 at 9:52

3 Answers 3

5
let s = NSString.self;
var str = s.init();

If you need the class, it's just:

print(s) // "NSString"

s is of Type "NSString.Type" it 's represent the Object class;

If you need the class of an object I think that you are searching "dynamicType":

let object = "toto"
let t = object.dynamicType // String.Type

var newObject = t.init("toto");
Sign up to request clarification or add additional context in comments.

Comments

3

As mentioned by others, the whole point is that Objective-C provides base class for all classes, while Swift does not. NSObject in obj-C provides alloc and init methods, hence one can expect that a descendant from NSObject will either implement or inherit those methods, hence you can have the shortcut-category you mentioned in your question.

In Swift there are no base classes, therefore you can not know which class (or other type) provides which initialisers. One way or another you will have to resort to specifying them for your purposes, and I think that protocols are the best way to do so.

E.g. consider this:

protocol DefaultInstantiatable {
    init()
}

extension DefaultInstantiatable {
    static func entity() -> Self {
        return Self()
    }
}

If your types adopt DefaultInstantiatable protocol then you could use clauses like:

struct Foo: DefaultInstantiatable {
    init() { }
}

class Bar: DefaultInstantiatable {
    required init() { }
}

let foo = Foo.entity()  // Creates an instance of Foo structure
let bar = Bar.entity()  // Creates an instance of Bar object

3 Comments

I can't get return Self() to work. Xcode 7.3.1 gives a syntax error.
It should work. There must be some reason why it errors in your case. Please create a separate question for that.
Ahhhh! My bad! And I just learned something cool from you-- I hadn't seen that this was in the context of a protocol extension. I like that! I was just generically trying to return Self() in a method and that wasn't working.
2

As I mentioned in my comment, the reason is that there is no base class in Swift. You can still do it by implementing your own base class or by subclassing NSObject.

class A : NSObject {}
class B : NSObject {}

extension NSObject {
    class func entity() -> Self {
        return self.init()
    }
}

A.entity()
B.entity()

NSObject.entity()

2 Comments

Isn't "dynamicType" enough?
dynamicType will not allow you to create an universal category, which is what the OP asked for.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.