4

Suppose an application for iOS displays an element that, when clicked, invokes a menu of actions for that element (say an UIActionSheet for example). The catch is, many clickable element such as this one may be present in every view in the application, so the action menu and its delegates must also be handled in any situation.

For example, the clickable element may be a photo of some product (UIButton with image background), that may appear in many different screens, and when clicked the user is presented with options such as "Buy", "See details", and so on.

How would you go about designing/implementing this kind of component with the associated behaviors, in a modular and reusable way?

It's important to keep the feature in a self-contained set of classes that can easily be tested separately and turned on/off when needed, and also not needing to insert code to every controller where the feature may be used.

Thanks!

2 Answers2

1

If you're implementing an app-wide UI element that can appear in more than one view, I would subclass your UIViewController (ie. ABCViewController). I usually do this at the beginning of every project just in case I need to implement something app-wide and all of my views are a subclass of that view controller with no code changes except for the one word in the header file. Then implement a function in your ABCViewController for showing the menu and a function to dismiss it. Compared to the Singleton class, I find it easier to memory manage the object and callback to the ViewController without having to deal with delegates.

Peter Cen
  • 276
  • 2
  • 8
  • this is a pragmatic solution, but what if I want to decouple the feature? Let's say I want to reuse the button in a lot of views, and have the appropriate behaviors work, but I could also remove the action menu altogether without changing the app in any fundamental way. Another way to look at this would be, what if I want to post this component at github and have other people improve on it? – Rafael Jannone Oct 23 '12 at 20:54
  • You can take out the functionality easily by removing the function from your ABCViewController. A better way to do it would be to subclass that menu into another class and then call it in your ABCViewController through a function which all your app can call. For example, I subclass my UITableViewController so they're all have the pull-down-to-refresh function but the actual class for it is in another class. You can easily host that class on GitHub. – Peter Cen Oct 24 '12 at 21:26
0

How about creating a singleton class that represents the feature you want? You can then just call the singleton object every time.

@interface MyClickableButtonWithImage : NSObject {
    UIButton *aButton;
}
+(MyClickableButtonWithImage)getInstance;
-(IBAction)buttonClicked:(id)sender;
@property (nonatomic, strong) IBOutlet UIButton *aButton;

@end

// In your .m files, this will get the singleton object
MyClickableButtonWithImage *myCBWI = [MyClickableButtonWithImage getInstance];
Chris F
  • 14,337
  • 30
  • 94
  • 192
  • this could work, but I noticed an ambiguity in my question. There could be many buttons such as these, like for example, a table with many products in it. Each product would show a menu of actions. Maybe the singleton idea could be applied to the menu itself? I'm new to iOS and objective-c, so pardon me if I'm saying non-sense. – Rafael Jannone Oct 23 '12 at 16:34
  • Yes, you can use the singleton idea at any level you want. So if you want the same table, the class containing the table will be the singleton. – Chris F Oct 23 '12 at 16:47
  • I ended up using a Singleton, even though it is harder to unit test, because it provided better feature isolation. Thanks! – Rafael Jannone Oct 31 '12 at 15:38