I'm creating a little MVC-sample-project as an iPhone-application in XCode, which is built completely with code and therefore doesn't use Interface Builder. First I'd like to show you the code I have so far.
Controller
The controller instantiates the model and the view and also contains a function which demonstrates the independency between model and view:
ViewController.h
#import <UIKit/UIKit.h>
#import "MainView.h"
#import "ProjectModel.h"
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
{
ProjectModel *model;
MainView *myMainView;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
model = [[ProjectModel alloc] init];
myMainView = [[MainView alloc] initWithFrame:CGRectMake(0, 0, 320, 468)];
[self.view addSubview:myMainView];
//test function to illustrate that view and model are independent
[self calculate];
}
- (void)calculate
{
int result = [model operationWithNumber:3 andAnotherNumber:5];
[myMainView showResult:result];
}
@end
Model
The class ProjectModel is responsible for the model of the project and is in this example for the sake of simplicity only responsible for summing up two numbers:
ProjectModel.h
#import <Foundation/Foundation.h>
@interface ProjectModel : NSObject
-(int)operationWithNumber:(int)number1 andAnotherNumber:(int)number2;
@end
ProjectModel.m
#import "ProjectModel.h"
@implementation ProjectModel
-(int)operationWithNumber:(int)number1 andAnotherNumber:(int)number2
{
return (number1 + number2);
}
@end
View
The view-class creates all the elements of the view and contains a function which displays the result of a calculation in a label. MainView.h
#import <UIKit/UIKit.h>
@interface MainView : UIView
{
UILabel *lblResult;
}
- (void)showResult:(int)result;
@end
MainView.m
#import "MainView.h"
@implementation MainView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 280, 50)];
lblTitle.text = @"This is my View";
[self addSubview:lblTitle];
lblResult = [[UILabel alloc] initWithFrame:CGRectMake(20, 200, 280, 50)];
lblResult.text = @"Result will be displayed here.";
[self addSubview:lblResult];
}
return self;
}
- (void)showResult:(int)result
{
lblResult.text = [NSString stringWithFormat:@"Resultat: %d", result];
}
@end
My Question:
I hope you understood the code so far. Based on the code above, I'd like to implement a button in the view-class which should calculate and display two numbers when the users clicks this button. Thus when the user clicks the button, the calculate-function in the ViewController should be called. I created a button with the following code in MainView.m:
UIButton *btnCalculate = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnCalculate setFrame:CGRectMake(20, 90, 280, 50)];
[btnCalculate setTitle:@"Calculate" forState:UIControlStateNormal];
[btnCalculate addTarget:self action:@selector(calculate:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btnCalculate];
The problem is this line in the code above:
[btnCalculate addTarget:self action:@selector(calculate:) forControlEvents:UIControlEventTouchUpInside];
how can I add a function from the controller as the action of the button. I know that the target should not be self, since the function should be called in the ViewController, but I have no idea how I could do that. Could anyone help me and tell me how I can solve this problem?
The only solution that I can see right now is that the complete GUI is created in the ViewController directly. But I don't think that this is a nice solution, since the main purpose of MVC is to avoid the mix of controller and view code in the same class.
Also I'm wondering whether this code generally conforms to the MVC-pattern propagated by Apple, since I'm pretty new to this design-pattern. I'd really appreciate a short feedback for this code.