0

I have a situation where I am converting an obj-c project to swift. it is as follows

    // few lazy property initializers as, 
    @property (nonatomic, strong) MyObject *property1;
    @property (nonatomic, strong) MyObject *property2;
    @property (nonatomic, strong) MyObject *property3;
    ... 

    // I keep an index value to map these into a dictionary for reference
    - (NSDictionary *)indexMap
    {
    if (!_indexMap)
    {
    _indexMap = @{ 
    @(index1) : [NSValue valueWithPointer:@selector(property1)],
    @(index2) : [NSValue valueWithPointer:@selector(property2)],
    ...
    };
    }
    return _indexMap;
    }

// other dictionary for index to class map
- (NSDictionary *)classMap
{
return @{ 

NSStringFromClass(@"MyClassA") : @(index1),
NSStringFromClass(@"MyClassB") : @(index1),
NSStringFromClass(@"MyClassC") : @(index1),

NSStringFromClass(@"MyClassD") : @(index2),
NSStringFromClass(@"MyClassE") : @(index2),

NSStringFromClass(@"MyClassF") : @(index3),
... 
};
}

// finally i have method to pass in the class name & it will first find corresponding index, then use the index to return the property selector. 

My concern is what is the swift like way of doing this ?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
nsuinteger
  • 1,503
  • 12
  • 21

1 Answers1

0

One way to do this would be to keep a list of callbacks which perform the initialisation. Here is one solution which is quite flexible, although simpler alternatives are certainly possible:

class ComponentManager {

    // Global singleton: ComponentManager.sharedManager
    static let sharedManager = ComponentManager()

    // Define a callback type which is used to create instances.
    // This is the lazy initialiser.
    typealias Constructor = () -> NSObject?

    private var constructor = [String: Constructor]()
    private var instances = [String: NSObject]()

    func register(name: String, constructor: Constructor) {
        self.constructor[name] = constructor
    }

    func instanceNamed(name: String) -> NSObject? {

        if let instance = instances[name] {
            return instance
        }

        guard let constructor = constructor[name] else {
            return nil
        }

        guard let instance = constructor() else {
            return nil
        }

        instances[name] = instance

        return instance
    }
}

To use it:

class A: NSObject {
    let foo: String
    init(foo: String) {
        self.foo = foo
    }
}

class B: NSObject {
    let bar: Int
    init(bar: Int) {
        self.bar = bar
    }
}

let manager = ComponentManager.sharedManager

// Register our classes. 
// Note the callback functions which actually perform the 
// initialisation, these are only called when the class is requested the 
// first time.
manager.register("A") { return A(foo: "fizz") }
manager.register("B") { return B(bar: 47) }

// Create some instances
let a = manager.instanceNamed("A") as? A
let b = manager.instanceNamed("B") as? B
let a2 = manager.instanceNamed("A") as? A

print("a = \(a?.foo)")
print("a2 = \(a?.foo)")
print("b = \(b?.bar)")
Luke Van In
  • 5,215
  • 2
  • 24
  • 45