3
votes

I'm trying to make a reusable UI component using a singleton so it's always the same instance used through the app when the UI component is show (only one of these can be shown at the same time obviously).

So I created a simple UIView subclass and defined a sharedInstance the Swift 1.2 way. Here's the code :

import UIKit

class MyView: UIView {
    static let sharedInstance = MyView()
}

The thing is I was wondering if there's a way to make this sharedInstance used when the view get called by a storyboard (so through init(coder:) method).

In ObjC that would be fairly easy as init methods can just return the desired object but in Swift I don't really know if it's something possible (as Swift init don't return the object).

EDIT : To add some context (some people don't understand WHY I'd want to do that). I'm trying to avoid a given UI component on which I have no control to eat up all the memory available.

This component is MKMapView which doesn't free the memory it takes after being uninstantiated. I tried several things but none did give me back all the memory took by the instantiation of MKMapView.

So I was trying to use a same instance of MKMapView everywhere to avoid having more used memory than necessary.

I asked the question to have a generic answer on the topic of having a sharedInstance returned when init(coder:) is called so that I could just use my component from any Storyboard file without having to put on the code to use the sharedInstance.

2
Why would a UI component ever need to be a singleton? Why not just create as many as you need, and connect them all to the same model so that they all look and act the same? - Caleb
FYI, when you instantiate a scene from a storyboard (storyboard.instantiateViewControllerWithIdentifier), you instantiate a view controller, not a view. When that view controller first references its view, then the view is instantiated. - Rob
@Caleb I'm trying different things to reduce MKMapView memory footprint (such as using the same instance and use it everywhere). My example was using UIView because I wanted a general answer. - Fantattitude
@Rob Yeah, what I meant is that when automatically instantiated because referenced by a VC the view uses the existing sharedInstance. - Fantattitude
Using a singleton for a UIView seems to be very, very inappropriate. Why would you care that the same instance is used? And if you do keep state around, don't you think a UIView is a very inappropriate place to store that data? - gnasher729

2 Answers

2
votes

Try awakeAfter(using:). This method is a good place for check if self is the one you need and replace it. Return sharedInstance and self will be replaced.

1
votes

One way is to just grab the scene directly out of the storyboard:

static let sharedInstance = (UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("identifier") as! UIViewController).view