I do it this way because the position of the arrow is updated and used by several classes.
in many cases, you can reduce the scope. this reduces the dependency between the components.
However, I'm not sure if this is a good or bad design decision. My thoughts are that since this is a non-critical piece of information (just a float), no harm happens when it is stored on a global scale. But my OOP heart hurts every time I say the word "global" to myself.
maybe you can move the state (float value) on ivar to the speedometer? For example: you will probably see only one type of speedometer: does it make sense to add it to what is a viewing model? or perhaps to his controller? (yes, it's a little hard to imagine a more concrete example without a source)
As an alternative, I have one-level styget, but, as far as I read, singletones are used when a developer wants to create one and only one instance of a specific object.
not necessary, and severe pain to maintain. most of the cocoa singleton that I saw should not be considered solitary, and caused a lot of headaches. even better, you can write programs that use zero singletones. It is perfect and easy to test. as is, programs / types that depend on the application controller have been compromised by testability and reuse.
Am I doing it right or is there a better way to do what I'm doing?
in the vast majority of cases, you can simply reduce the scope and localize it by deleting the global state. with less effort, you can remove this value as global - this is best.
although this is not good ... let's assume that you really really really have to enter a global state:
- do not use singleton. chances are you will rewrite it when you want to reuse it. it's a sugar coating that is ugly. if your application controller is messed up because of too much global state, at least the fact that you have too much global state will be obvious.
- keep your global state in your application controller. Your application controller is responsible for its initialization, lifetime, and access.
- provide this state to dependencies, so they do not refer to the global domain (or even do not know) (application controller). then you can minimize exposure.
there is also a clear distinction between global state and application / runtime state. the global state must be liquidated. The execution state is not a global state, but a local execution context. execution status can be re-entered at the correct level, changed and updated, verified and reused predictably. a good design will introduce a state of execution when necessary, and at the right level, avoiding a global state.
Update
Your example is pretty close to what I imagined based on the description in the OP. This provided some additional features. So, the example below (you will need some additions in obvious areas to put it all together) demonstrates how you can update controller interfaces, and at the end there are two free “other” methods that once again illustrate how to use them:
@interface MONArrowPosition : NSObject { float arrowPosition; } @end @implementation MONArrowPosition - (id)initWithPosition:(float)position { self = [super init]; if (nil != self) { arrowPosition = position; } return self; } @end @interface MyViewController1 : UIViewController { MONArrowPosition * arrowPosition; // << may actually be held by the model } @end @implementation MyViewController1 - (void)applyRotation { [self rotateLayer:arrow from:self.arrowPosition to:callStatus speed:METER_SPEED]; } @end @interface MyViewController2 : UIViewController { MONArrowPosition * arrowPosition; // << may actually be held by the model } @end @implementation MyViewController2 - (void)viewDidLoad { [super viewDidLoad]; /* ... */ [self.slider addTarget:self action:@selector(sliderValueDidChange) forControlEvents:controlEvents]; } - (void)sliderValueDidChange { self.arrowPosition.arrowPosition = self.slider.value; [self arrowPositionDidChange]; } @end /* elsewhere: */ - (void)initializeArrowPosition { /* The variable is set to a default of 0.0f */ MONArrowPosition * arrowPosition = [[MONArrowPosition alloc] initWithPosition:0.0f]; /* ... */ } - (IBAction)someActionWhichPushesMyViewController1 { // depending on the flow of your app, the body of initializeArrowPosition // *could* be right here MyViewController1 * viewController = [[MyViewController1 alloc] initWithNibName:nibName bundle:bundle]; viewController.arrowPosition = self.arrowPosition; /* push it */ }
and then, if MyViewController1 pushes MyViewController2, finding and adjusting the position of the arrow will be easy. view controllers can also share some information in models. with the global in your sample, you cross many implementations, which adds connectivity, increases dependency, etc., so if you can use this approach and localize the execution state, you can start well. then you can use any number of view controllers with any number of MON ARROPosition elements, and they will not be affected by the global state. again, I can’t get too specific use of the provided samples, but I think this should illustrate the concepts that I initially set out quite well (I don’t think that a review of the project is needed).