0

全部。我正试着按照iPhone的屏幕制作球弹跳的教程。本教程在MVC方案中构建应用程序。在涉及到View实现中的drawRect方法时,我无法绕开这个概念。石英2D MVC图

这是我的模型的头文件:

#import <Foundation/Foundation.h> 
#import "TestView.h" 

#define BALL_SIZE 20.0 
#define VIEW_WIDTH 320.0 
#define VIEW_HEIGHT 460.0 

@interface TestModel : NSObject 
{ 
    TestView* ball; 
    CGPoint ballVelocity; 
    CGFloat lastTime; 
    CGFloat timeDelta; 
} 

- (void) updateModelWithTime:(CFTimeInterval) timestamp; 
- (void) checkCollisionWithScreenEdges; 

@property (readonly) TestView* ball; 

@end 

教程指示我的用户覆盖的NSObject的init方法。我还包含用于控制 “动画” 的逻辑方法:

- (id) init { 
     self = [super init]; 

     if (self) { 
      ball = [[TestView alloc] initWithFrame: CGRectMake(0.0, 0.0, BALL_SIZE, BALL_SIZE)]; 

      // Set the initial velocity for the ball 
      ballVelocity = CGPointMake(200.0, -200.0); 

      // Initialize the last time 
      lastTime = 0.0; 
     } 

     return self; 
    } 

- (void) checkCollisionWithScreenEdges { 
    // Left Edge 
    if (ball.frame.origin.x <= 0) { 
     ballVelocity.x = abs(ballVelocity.x); 
    } 

    // Right Edge 
    if (ball.frame.origin.x >= VIEW_WIDTH - BALL_SIZE) { 
     ballVelocity.x = -1 * abs(ballVelocity.x); 
    } 

    // Top Edge 
    if (ball.frame.origin.y <= 0) { 
     ballVelocity.y = abs(ballVelocity.y); 
    } 

    // Bottom Edge 
    if (ball.frame.origin.y >= VIEW_HEIGHT - BALL_SIZE) { 
     ballVelocity.y = -1 * abs(ballVelocity.y); 
    } 
} 

- (void) updateModelWithTime:(CFTimeInterval) timestamp { 
    if (lastTime == 0.0) { 
     // initialize lastTime if first time through 
     lastTime = timestamp; 
    } else { 
     // Calculate time elapsed since last call 
     timeDelta = timestamp - lastTime; 

     // Update the lastTime 
     lastTime = timestamp; 

     [self checkCollisionWithScreenEdges]; 

     // Calculate the new position of the ball 
     CGFloat x = ball.frame.origin.x + ballVelocity.x * timeDelta; 
     CGFloat y = ball.frame.origin.y + ballVelocity.y * timeDelta; 

     ball.frame = CGRectMake(x, y, BALL_SIZE, BALL_SIZE); 
    } 
} 

观实现文件如下:

#import "TestView.h" 

@implementation TestView 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
    } 
    return self; 
} 

// Only override drawRect: if you perform custom drawing. 
// An empty implementation adversely affects performance during animation. 
- (void)drawRect:(CGRect) rect { 

} 
@end 

最后,我的视图控制器:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    gameModel = [[TestModel alloc] init]; 

    [self.view addSubview:gameModel.ball]; 

    // Set up the CADisplayLink for the animation 
    gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateDisplay:)]; 

    // Add the display link to the current run loop 
    [gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
} 

- (void) updateDisplay:(CADisplayLink *) sender { 
    [gameModel updateModelWithTime:sender.timestamp]; 
} 

好的,现在我已经看到了代码的结构(希望我已经给出了足够的结果),我可以解决我的问题。因此,当我添加任何drawRect时,绘制了一个新的对象,并且没有通过模型逻辑方法获得“动画”。

现在我有一个弹跳广场。当我尝试用drawRect中的椭圆填充正方形时,我得到一个新对象,绘制了我想要的,刚好位于0,0,而弹跳方块仍处于活动状态。

我敢肯定,我失去了一些东西真的很大这里,但我一直在敲打我的头靠在墙上几个小时,不能弄明白。任何帮助将不胜感激!

回答

0

这里有几件事:

1-你有没有覆盖视图类在SB到TestView?
2-看着你的代码,我没有看到你的模型如何通过你的控制器连接到你的视图。从MVC模型中回想一下,控制器处于顶部并向下(金字塔样式)向模型和视图进行对话,因此,在视图控制器中的某处:
a)您需要实例化您的模型
b)获取值从你的模型,并将其传递到您的视图变量 - 这将在drawRect中

最后但并非最不重要的,查找setNeedsDisplay这是调用并刷新视图的方式调用。

希望这有助于不损害任务。

+0

嘿,谢谢你的回复。我用我的View Controller实现更新了我的初始职位。 SB代表什么? = /从我可以收集,我正确地实例化模型并添加TestView。 – 2013-02-11 13:25:03

+0

SB = Storyboard。我建议你花一些时间在CS193P MVC上(我认为课程#1或#2)iTunes课程。在viewDIdLoad中,您正在正确地实例化模型,但不能将该模型添加为子视图。它不是一个UIView,它是一个模型。同样,你的浏览器实例化模型,然后应该通过属性发送信息到TestView类。 – Spectravideo328 2013-02-11 13:36:05

+0

好的,我会检查出来的。感谢您的建议。另外,是的,我已经将视图类更改为SB中的TestView。 – 2013-02-11 13:48:57