I’m reorganising old code by creating a custom UIView
to separate UI elements that belong in the View
from those that belong in the ViewController.
Several buttons previously included in several ViewControllers are now in a single custom UIView
and I need them to send messages to methods inside the current viewController
so users can navigate to other viewControllers.
This answer on SO suggests using a delegate while this answer to the same question suggests not using a delegate. This answer to a different question also makes sense. But I can’t tell which one is best for my needs. I'm reluctant to do anything that might break the current appDelegate
which manages a MultiviewViewController
(which in turn switches between ViewControllers).
So my question is:
what is the safest way to redefine the target-action method so UIButtons
relay messages to methods in my UIViewController
?
A ‘skinny’ version of my code below shows what I am trying to do
safe - a clarification
By safe, I simply meant reliable i.e. not likely to introduce unintended consequences at runtime. The underlying motivation for the question is to keep UI elements where they belong - i.e. in a
UIView
or in aUIViewController
- without breaking an existing app.
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
#import "CustomView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGRect rect = [UIScreen mainScreen].bounds;
float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
CGRect screenFrame = CGRectMake(0, statusBarHeight, rect.size.width, rect.size.height - statusBarHeight);
self.view = [[UIView alloc] initWithFrame: screenFrame];
self.view.backgroundColor = [UIColor lightGrayColor];
CustomView *cv = [[CustomView alloc]initWithFrame:screenFrame]; //create an instance of custom view
[self.view addSubview:cv]; // add to your main view
}
- (void)goTo1 {
NSLog(@"switch to Family 1");
// * commented out from the original app
// MultiviewAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
// [parent setSelectedZone:1];
// [appDelegate displayView:1];
}
- (void)goTo2 {
NSLog(@"switch to Family 2");
// * commented out from the original app
// MultiviewAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
// [parent setSelectedZone:2];
// [appDelegate displayView:1];
}
- (void)goTo3 {
NSLog(@"switch to Family 3");
// * commented out from the original app
// MultiviewAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
// [parent setSelectedZone:3];
// [appDelegate displayView:1];
}
@end
CustomView.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface CustomView : UIView {
}
@end
CustomView.m
#import <Foundation/Foundation.h>
#import "CustomView.h"
@interface CustomView ()
- (UIViewController *)viewController;
@end
@implementation CustomView : UIView
- (UIViewController *)viewController {
if ([self.nextResponder isKindOfClass:UIViewController.class])
return (UIViewController *)self.nextResponder;
else
return nil;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:[UIScreen mainScreen].bounds];
if (self) {
[self threeButtons];
}
return self;
}
- (void)buttonPicked:(UIButton*)button {
NSLog(@"Button %ld : - send message to UIViewController instead.”, (long int)[button tag]);
switch (button.tag) {
case 1:
// [self goTo1];
break;
case 2:
// [self goTo2];
break;
case 3:
// [self goTo3];
break;
default:
break;
}
}
- (void)threeButtons {
int count = 3;
int space = 5;
float size = 60;
for (int i = 1; i <= count; i++) {
CGFloat x = (i * (size + space)) + 40;
CGFloat y = 100;
CGFloat wide = size;
CGFloat high = size;
UIButton *buttonInView = [[UIButton alloc] initWithFrame:CGRectMake(x, y, wide, high)];
[buttonInView setTag:i];
[buttonInView addTarget:self action:@selector(buttonPicked:) forControlEvents:UIControlEventTouchUpInside];
buttonInView.layer.borderWidth = 0.25f;
buttonInView.layer.cornerRadius = size/2;
[buttonInView setTitle:[NSString stringWithFormat:@"%i", i] forState:UIControlStateNormal];
[buttonInView setTitleColor: [UIColor blackColor] forState:UIControlStateNormal];
buttonInView.layer.borderColor = [UIColor blackColor].CGColor;
buttonInView.backgroundColor = UIColor.whiteColor;
[self addSubview:buttonInView];
}
}
@end