这课主要是以一个计算器一个用为例子,教你怎么使用XCode,如何使用MVC设计模式创建应用。

(1)新建一个single view application模版的应用

打开xcode并点击“创建一个新xcode项目”,进入项目创建界面,这个界面让我们为应用选择一个模板。接着选择“single view application”模板,单击next按钮,进入项目详细信息界面。

其中Company Identifier用来标志你的应用,要是唯一的,不要有冲突。class prefix通常与应用的名字一样。这个use storyboard是ios5新特性,它允许把所有的view同时放到屏幕上,所以能看到它们之间的互动。storyboard能让你在屏幕上看到MVC群的结构图,看到MVC之间的关系。

接着单击next按钮,进入选择保存项目目录界面,选择好后单击create按钮,就创建好了项目。

MainStoryboard.storyboard是我们MVC的view,所有MVC的所有view都在这里。在我们的例子里,storyboard会包含所有controller的view。系统不会自动创建model,因为系统不知道它是什么。

接下来构建计算器,需要一些控件如按钮、文本框、显示区域。这可以通过单击右上角utilities按钮实现,它会弹出一个区域:上部分叫inspector,用来显示所选内容的更多信息;下半部分可以认为是一个向导,绘制view的向导,我们需要这个向导,因为我们需要对象库。

还记得之前的那个MVC图吗?controller有个绿色箭头能够向view发话。

controller肯定需要和view对话,告诉它显示内容、计算结果、输入内容,所以要在controller中创建一个outlet到veiw里。实现这点不用打代码,只需按住键盘control键,从显示上拖出一条线到代码上即可。label已经有个strong指针了,因为父窗口view已经有了strong指针指向它,所以label只需weak指针。IBOutlet这个类型没有具体内容,只是xcode用来跟踪哪个property是outlet的。controller已经准备好向label发话了,synthesize已经生成setter和getter,那什么时候调用呢?setter用来设置指针,当storyboard被读取画面出现在屏幕上时,ios就会调用setter去创建连接到outlet,当想要和label对话时就去调用getter。回到对象库拖出round rect button到显示界面上,现在要考虑controller和veiw的另一个连接,target action。所以controller要有一个target来接收键盘按钮发送的action(用户按下按钮),操作只需按住control将按钮拖出到h文件,IBAction实际上就是void,用ibaction是要让xcode知道这是个action。这个target action就是当按钮被按,它就发消息给controller,消息附带参数,这个参数就是发送者自己,这里就是按钮。复制粘贴按钮,也会复制它的target actin,所以按钮都会发送一样的target action。

以下是CalculatorViewController.h文件的代码:

#import <UIKit/UIKit.h>

@interface CalculatorViewController : UIViewController {
    UILabel *display;
}

@property (strong, nonatomic) IBOutlet UILabel *display;
- (IBAction)digitPressed:(id)sender;
- (IBAction)operationPressed:(id)sender;
- (IBAction)enterPressed;

@end

CalculatorViewController.m文件的代码:

#import "CalculatorViewController.h"

#import "CalculatorBrain.h"

@interface CalculatorViewController ()

@property (nonatomic) BOOL userIsIntheMiddleOfEnterNumber;
@property (nonatomic, strong) CalculatorBrain *brain;

@end

@implementation CalculatorViewController

@synthesize display = _display;
@synthesize userIsIntheMiddleOfEnterNumber = _userIsIntheMiddleOfEnterNumber;
@synthesize brain = _brain;

-(CalculatorBrain *)brain{
    if (!_brain) {
        _brain = [[CalculatorBrain alloc] init];
    }
    return _brain;
}

- (IBAction)digitPressed:(UIButton *)sender {
    NSString *digit = [sender currentTitle];
    if (self.userIsIntheMiddleOfEnterNumber) {
        self.display.text = [self.display.text stringByAppendingString:digit];
    } else {
        self.display.text = digit;
        self.userIsIntheMiddleOfEnterNumber = YES;
    }
}

- (IBAction)operationPressed:(UIButton *)sender {
    if (self.userIsIntheMiddleOfEnterNumber) {
        [self enterPressed];
    }
    double result = [self.brain performOperation:[sender currentTitle]];
    NSString *resultString = [NSString stringWithFormat:@"%g",result];
    self.display.text = resultString;
}

- (IBAction)enterPressed {
    [self.brain pushOperand:[self.display.text doubleValue]];
    self.userIsIntheMiddleOfEnterNumber = NO;
}
@end

现在需要建个model,我们已经有了controller和view还要有model。单击菜单里File—NEW—NEW File创建文件,选择objective-c class,单击next,取名为CalculatorBrain保存位置与其它文件一样。

需要一个栈来保持操作数、入栈运算、出栈运算等。怎么去实现一个栈?一个很简单的办法是使用数组。我们需要private接口,因为这个栈不是公共的,入栈出栈操作全在model里进行。当property创建的时候值是0或nil,那么向nil发送消息就什么也不会发生,因此需要一个构造函数来设置它,只需要在getter方法里判断实体变量是否为空,如果为空就为它分配一个数组,同时也只分配一次,这叫延迟实例化。synthesize不会自动分配内存空间,synthesize只有一个变量指针,需要自己来分配空间。

以下是CalculatorBrain.h文件的代码:

#import <Foundation/Foundation.h>

@interface CalculatorBrain : NSObject

-(void)pushOperand:(double)operand;
-(double)performOperation:(NSString *)operation;

@end

CalculatorBrain.m文件的代码如下:

#import "CalculatorBrain.h"

@interface CalculatorBrain()

@property (nonatomic, strong) NSMutableArray *operandStack;

@end

@implementation CalculatorBrain

@synthesize operandStack = _operandStack;

-(NSMutableArray *)operandStack{
    if (_operandStack == nil) {
        _operandStack = [[NSMutableArray alloc] init];
    }
    return _operandStack;
}

-(void)pushOperand:(double)operand{
    NSNumber *operandObject = [NSNumber numberWithDouble:operand];
    [self.operandStack addObject:operandObject];
}

-(double)popOperand{
    NSNumber *operandObject = [self.operandStack lastObject];
    if (operandObject != nil) {
        [self.operandStack removeLastObject];
    }
    return [operandObject doubleValue];
}

-(double)performOperation:(NSString *)operation{
    double result = 0;
    if ([operation isEqualToString:@"+"]) {
        result = [self popOperand] + [self popOperand];
    }else if([operation isEqualToString:@"*"]){
        result = [self popOperand] * [self popOperand];
    }
    return result;
}

@end

 

posted on 2012-12-11 18:00  写下一生的程序  阅读(1050)  评论(1编辑  收藏  举报