Skip to content
Roland Moers edited this page Oct 31, 2016 · 14 revisions

This page will describe how to use RMActionController in your project.

Basic

RMActionController does not come with any content view (the one in the middle between all those buttons) for presentation. This means presenting an RMActionController only presents a set of buttons. For this task UIAlertController might be a better option.

The strength of RMActionController is that it can present any UIView as content view in an UIActionSheet/UIAlertController like fashion. To add a content view to RMActionController it is usually subclassed. This project contains two subclasses (RMCustomViewActionController and RMMapActionController) which give two examples for a subclass of RMActionController. In addition, you might want to take a look at the following projects for more examples on how to use RMActionController:

Subclassing

The remainder of this wiki page will explain how to create a subclass of RMActionController.

Creating your subclass

First create your own subclass of RMActionController. I assume you know how to do that. When creating your subclass you can specify a generic type. This type should be set to the class of the content view you are about to show. For example, if you are planning to present an MKMapView, the generic should be set to MKMapView.

Objective-C

@interface RMMapActionController : RMActionController<MKMapView *>
@end

Swift

class MapActionController: RMActionController<MKMapView> {
}

Implementing your subclass

When subclassing RMActionController you only have to overwrite one method. This method is called actionControllerWithStyle:title:message:selectAction:andCancelAction:. For example, if you want to present an MKMapView your implementation may look like follows:

Objective-C

- (instancetype)initWithStyle:(RMActionControllerStyle)aStyle title:(NSString *)aTitle message:(NSString *)aMessage selectAction:(RMAction *)selectAction andCancelAction:(RMAction *)cancelAction {
    self = [super initWithStyle:aStyle title:aTitle message:aMessage selectAction:selectAction andCancelAction:cancelAction];
    if(self) {
        self.contentView = [[MKMapView alloc] initWithFrame:CGRectZero];
        self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
        
        NSDictionary *bindings = @{@"mapView": self.contentView};
        [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[mapView(>=300)]" options:0 metrics:nil views:bindings]];
        [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[mapView(200)]" options:0 metrics:nil views:bindings]];
    }
    return self;
}

Swift

required override init?(style aStyle: RMActionControllerStyle, title aTitle: String?, message aMessage: String?, select selectAction: RMAction<MKMapView>?, andCancel cancelAction: RMAction<MKMapView>?) {
    super.init(style: aStyle, title: aTitle, message: aMessage, select: selectAction, andCancel: cancelAction);
    
    self.contentView = MKMapView(frame: .zero)
    self.contentView.translatesAutoresizingMaskIntoConstraints = false
    
    let bindings = ["contentView": self.contentView];
    self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "[contentView(>=300)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: bindings))
    self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[contentView(200)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: bindings))
}

If you are using Swift you also need to to overwrite the initializer for NSCoder.

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder);
}

Additional options

Sometimes you need to disable the blurred background for the content view you want to show (for example, this is the case for presenting an MKMapView). If you encounter such a case you need to overwrite the getter of the property disableBlurEffectsForContentView and always return true.

Objective-C

- (BOOL)disableBlurEffectsForContentView {
    return YES;
}

Swift

override var disableBlurEffectsForContentView:Bool {
    get {
        return true;
    }
    set {
    }
}

Presentation

Presenting your subclass of RMActionController works by using standard Apple API.

- (IBAction)openActionController:(id)sender {
    RMAction *selectAction = [RMAction<MKMapView *> actionWithTitle:@"Select" style:RMActionStyleDone andHandler:^(RMActionController<MKMapView *> *controller) {
        NSLog(@"Action controller selected location: %f, %f", controller.contentView.centerCoordinate.latitude, controller.contentView.centerCoordinate.longitude);
    }];
    
    RMAction *cancelAction = [RMAction<MKMapView *> actionWithTitle:@"Cancel" style:RMActionStyleCancel andHandler:^(RMActionController<MKMapView *> *controller) {
        NSLog(@"Action controller was canceled");
    }];
    
    RMMapActionController *actionController = [RMMapActionController actionControllerWithStyle:RMActionControllerStyleWhite title:@"Test" message:@"This is a map action controller.\nPlease select a location and tap 'Select' or 'Cancel'." selectAction:selectAction andCancelAction:cancelAction];
    
    //Now just present the date selection controller using the standard iOS presentation method
    [self presentViewController:actionController animated:YES completion:nil];
}
func openMapActionController() {
    let selectAction = RMAction<MKMapView>(title: "Select", style: RMActionStyle.done) { controller in
        print("Action controller selected location: ", controller.contentView.centerCoordinate.latitude, controller.contentView.centerCoordinate.longitude)
    }
    
    let cancelAction = RMAction<MKMapView>(title: "Cancel", style: RMActionStyle.cancel) { _ in
        print("Map action controller was canceled")
    }
    
    let actionController = MapActionController(style: .white, title: "Test", message: "This is a map action controller.\nPlease choose a date and press 'Select' or 'Cancel'.", select: selectAction, andCancel: cancelAction)
    
    //Now just present the date selection controller using the standard iOS presentation method
    present(actionController, animated: true, completion: nil)
}

There are some options you might want to set before presenting your subclass of RMActionController.

Clone this wiki locally