1

In Objective-C, this worked well for a Singleton in Interface Builder

static Universe *instance;

+ (Universe *)instance {
    return instance;
}

+ (id)hiddenAlloc {
    return [super alloc];
}

+ (id)alloc {
    return [self instance];
}

+ (void)initialize {
    static BOOL initialized = NO;
    if (!initialized) {
        initialized = YES;
        instance = [[Universe hiddenAlloc] init];
    }
}

and due to the overwriting of the alloc, IB would pick up the only instance of Universe

Is this possible in Swift? [I've gotten stuck with my solution, which is here on Github.]

Community
  • 1
  • 1
Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
  • 1
    No because there is no such thing as `alloc` in Swift. You are munging fundamental memory management, and Swift won't let you do that. If this is important to you, why not write this part of the code in Objective-C? – matt Jun 08 '16 at 19:43
  • @matt Thanks for that, agreed. I'm trying to imagine a hybrid where the singleton-ness is in Objective-C and then the `Universe` is a Swift subclass. Seems to me like that's impossible since the `initialize` must be tied to the specific class, right? – Dan Rosenstark Jun 08 '16 at 19:46
  • No, `initialize` can be called for subclasses. That's why a good `initialize` always checks what class this actually is. – matt Jun 08 '16 at 19:51
  • This could be fun, I'll see what I come up with, thank you! – Dan Rosenstark Jun 08 '16 at 19:53
  • Hi @matt I posted an answer below. It's close to working, but it's somehow losing `IBOutlet` variables (though its hash value and memory address remain fixed). Any suggestions, hints, guidance (or discouragement, if that's what's necessary) would be welcome. Thanks! – Dan Rosenstark Jun 08 '16 at 20:38
  • @matt I posted a clean test project to Github at https://github.com/drosenstark/SingletonInSwift to make it very easy if one wanted to take a look. Thanks! – Dan Rosenstark Jun 09 '16 at 14:25

1 Answers1

0

This is a start (I think). Superclass in Objective-C.

Please check it out on Github... any help appreciated!

Singleton.h (must be in Bridging Header)

#import <Foundation/Foundation.h>

@interface Singleton : NSObject

+ (Singleton *)instance;

@end

Singleton.m

#import "Singleton.h"

@implementation Singleton

static Singleton *instance;

+ (Singleton *)instance {
    return instance;
}

+ (id)hiddenAlloc {
    return [super alloc];
}

+ (id)alloc {
    return [self instance];
}

+ (void)initialize {
    static BOOL initialized = NO;
    if (!initialized) {
        initialized = YES;
        instance = [[self hiddenAlloc] init];
    }
}

@end

Universe.swift

import UIKit

// MARK: - convenience access
let universe = Universe.sharedInstance

@objc(Universe)
class Universe : Singleton {

    static let sharedInstance = Universe()

    override class func instance() -> Singleton {
        return sharedInstance
    }
}

The Universe object is always showing the same hash (and memory address), but it's not holding on to its IBOutlet variables... so this is still 100% broken, but it's a start (probably).

Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
  • It's pretty odd. The `initialize` is getting called exactly twice (once for `Universe`) and everything else seems so correct! Not sure what's up with my `IBOutlets`... anyway – Dan Rosenstark Jun 08 '16 at 20:49
  • If you really want a 'singleton' then you should have a private init method so that nothing else can create your singleton instance. You should also make the class as final. – Gargoyle Jun 08 '16 at 23:58
  • Thanks @Gargoyle i will do that as soon as I have the thing working. – Dan Rosenstark Jun 09 '16 at 03:04
  • It's easier to play with now, adding GitHub link – Dan Rosenstark Jun 09 '16 at 14:23
  • As you can see here -- https://github.com/drosenstark/SingletonInSwift -- the issue is that each time the `init` is called, while it does provide the same object, all the properties get set to their initial assignment (and `willSet` etc. is not run during the init) – Dan Rosenstark Jun 09 '16 at 18:16