首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在iOS中等待用户交互的设计模式?

在iOS中等待用户交互的设计模式?
EN

Stack Overflow用户
提问于 2013-02-21 14:04:06
回答 1查看 582关注 0票数 2

我正在为iOS开发一个BlackJack游戏。跟踪当前状态和需要做的事情变得越来越困难。例如,我有一个跟踪当前游戏的C++类:

代码语言:javascript
复制
class Game {
  queue<Player> playerQueue;
  void hit();
  void stand();
}

目前我正在使用事件实现它(方法A):

代码语言:javascript
复制
- (void)hitButtonPress:(id)sender {
  game->hit();
}

void Game::hit() {
  dealCard(playerQueue.top());
}

void Game::stand() {
  playerQueue.pop();
  goToNextPlayersTurn();
}

随着越来越多的选项被添加到游戏中,为每个选项创建事件变得单调乏味,很难跟踪。

我想到的另一种实现方式是这样的(方法B):

代码语言:javascript
复制
void Game::playersTurn(Player *player) {
  dealCards(player);
  while (true) {
    string choice = waitForUserChoice();
    if (choice == "stand") break;
    if (choice == "hit")
      dealCard(player);
    // etc.
  }
  playerQueue.pop();
  goToNextPlayersTurn();
}

其中,waitForUserChoice是一个特殊函数,它允许用户与UIViewController交互,一旦用户按下按钮,就会将控制权返回给playersTurn函数。换句话说,它会暂停程序,直到用户单击一个按钮。

使用方法A,我需要在每次需要用户交互时拆分我的功能。方法B让一切都保持在更好的控制之下。从本质上讲,方法A和方法B之间的区别如下:

答:

代码语言:javascript
复制
function A() {
  initialize();
  // now wait for user interaction by waiting for a call to CompleteA
}

function CompleteA() {
  finalize();
}

B:

代码语言:javascript
复制
function B() {
  initialize();
  waitForUserInteraction();
  finalize();
}

注意B是如何使代码更有条理的。有没有办法用Objective-C做到这一点呢?或者有没有我没有推荐的不同的方法呢?

我能想到的第三种选择是使用有限状态机。我听说过一些关于他们的事情,但我确信这对我在这种情况下是否有帮助。

对于我的问题,推荐的设计模式是什么?

EN

回答 1

Stack Overflow用户

发布于 2013-02-21 18:28:34

我理解你所面临的困境。当我第一次启动iOS的时候,我有一段非常艰难的时间来考虑放弃对操作系统的控制。

通常,iOS会鼓励您使用方法A。通常,您的ViewController中有在方法A()中设置的变量,然后在CompleteA()中检查这些变量,以验证A()是否先运行等等。

关于你关于有限状态机的问题,我认为它可能会帮助你解决你的问题。我用iOS写的第一个东西是一个有限状态机(这是一个相当糟糕的代码),但是你可以看看这里(在first ViewController.m的底部附近:

https://github.com/esromneb/ios-finite-state-machine

一般的想法是将其放入.h文件中的@interface块中

代码语言:javascript
复制
static int state = 0;
static int running = 0;

在你的.m中,你有这个:

代码语言:javascript
复制
- (void) tick {

    switch (state) {
        case 0:
            //this case only runs once for the fsm, so setup one time initializations

            // next state
            state = 1;

            break;
        case 1:
            navBarStatus.topItem.title = @"Connecting...";
            state = 2;
            break;
        case 2:
            // if something happend we move on, if not we wait in the connecting stage
            if( something )
                state = 3;
            else
                state = 1;
            break;
        case 3:
            // respond to something

            // next state
            state = 4;
            break;
        case 4:
            // wait for user interaction
            navBarStatus.topItem.title = @"Press a button!";
            state = 4;

            globalCommand = userInput;

            // if user did something
            if( globalCommand != 0 )
            {
                // go to state to consume user interaction
                state = 5;  
            }

            break;

        case 5:
            if( globalCommand == 6 )
            {
                // respond to command #6
            }
            if( globalCommand == 7 )
            {
                // respond to command #7
                }

                        // go back and wait for user input
                        state = 4;
            break;

        default:
            state = 0;
            break;
    }

    if( running )
    {
        [self performSelector:@selector(tick) withObject:nil afterDelay:0.1];
    }
}

在本例中(从github上的修改而来),globalCommand是一个表示用户输入的整数。如果globalCommand为0,则有限状态机仅在状态4中旋转,直到globalCommand为非零。

要启动有限状态机,只需将running设置为1,然后从viewController调用self tick。FSM将每隔0.1秒“滴答”一次,直到running设置为0。

在我最初的FSM设计中,我必须对运行自己软件的windows计算机的用户输入和网络输入做出响应。在我的设计中,windows PC也运行类似但不同的FSM。对于这个设计,我使用NSMutuableArray构建了两个命令的先进先出队列对象。用户交互和网络数据包将命令入队到队列中,而FSM将出队项目并对其作出响应。我最终使用了https://github.com/esromneb/ios-queue-object来处理队列。

如果您需要任何澄清,请发表意见。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14995611

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档