0

Possible Duplicate:
What should my Objective-C singleton look like?

I am trying to understand the use of singletons. I have red to be careful with them, but also that they can have their positive uses.

My Scenario:

At the moment I have a test Project set up. One ViewController has a button that needs to perform an action.

The FirstViewController has a UIWebView on it.

I am using Storyboard and ContainerView, so I am able to see both ViewControllers at the same time.

In the First ViewController I have this code in my .m file:

static FirstViewController *sharedController = nil;

+ (FirstViewController *)sharedController {

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    //BBCSermonTabBarViewController *myVC = (BBCSermonTabBarViewController *)[storyboard instantiateViewControllerWithIdentifier:@"BBCNews"];

    if(sharedController == nil)
        sharedController = (FirstViewController *)[storyboard instantiateViewControllerWithIdentifier:@"firstViewController"];

    return sharedController;
}

And I also have a method that changes the alpha it like so:

-(void)hideWebView
{
    _webView.alpha = 0.3;
}

Now in my Second View controller I have this code:

-(IBAction)hideWebViewFromAnotherViewController
 {
   [[FirstViewController sharedController] hideWebView];
 }

Should that action button now change the alpha of the webView in the other ViewController?

if not what am I doing wrong??

Thanks in advance:-)

Community
  • 1
  • 1
jwknz
  • 6,598
  • 16
  • 72
  • 115
  • I prefer http://stackoverflow.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc for singletons personally. – Scott Robertson Jan 25 '13 at 23:28

3 Answers3

1

For safety's sake, and because with libdispatch it's so easy, you should protect the singleton creator with a dispatch_once() call instead of doing an if() check.

+ (FirstViewController *)sharedController {

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

    static dispatch_once_t token;
    dispatch_once(&token, ^{

    sharedController = (FirstViewController *)[storyboard instantiateViewControllerWithIdentifier:@"firstViewController"];
    });

    return sharedController;
}

The token is used like a semaphore to protect the block and make sure it only gets called once during the run of your program; it's protected from races and simultaneous reads.

iluvcapra
  • 9,436
  • 2
  • 30
  • 32
1

I can appreciate your goal to understand singletons better, but I would suggest not using a singleton unless you have to.

I don't think it is appropriate in most UI scenarios(I have never needed one) to have singletons. I suggest one of the following methods for communicating between objects:

  • Hold a reference to objects that you want to communicate with. Simply add a property and save a reference to the class that needs to be called later. You can make it a weak reference if it works in your scenario.

  • Use the delegate pattern that is common with iOS/Objective-c apps. Same as above, except define a protocol instead. Normally the property is called delegate. This allows other views to communicate using a common interface.

  • Use notification center. I don't prefer this option for most cases, but if there is an event that a lot of views might need to know about, and you don't want to deal with passing references to objects, it might be a good option.

Singletons work best for non-UI code in my experience, when you actually need to rely on the singleton behavior of instantiating the class upon first use. In your situation it looks like the only reason you're using a singleton is to make that view controller accessible across your entire app.

Kekoa
  • 27,892
  • 14
  • 72
  • 91
0

It should work. Potential problems: _webView is nil, [FirstViewController sharedController] is not returning a valid reference. Set a breakpoint on hideWebViewFromAnotherViewController and step through, making sure everything is defined when you think it is.

jsd
  • 7,673
  • 5
  • 27
  • 47