0

ここで私がやりたいこと

アクションを起こす前にループとかそういうのをやりたくて、今はこんな感じでやってます

//check if it's multiplayer mode
if ([PlayerInfo instance].playingMultiplayer == YES)
{
   //no cards has been played
   //the while and NSRunLoop combination seems harsh
   while ([PlayerInfo instance].cardsPlayed == NULL) 
   {
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
   }
   //after the "loop thing" done, execute this method
   //take out cards with the broadcasted cardsPlayed, it's event based
   [self takeOutCards:[PlayerInfo instance].cardsPlayed];
}
//single player, don't bother this
else
    {
       //AI logic, select possible best cards
       NSArray * bestCards = [playerLogic selectBestMove];
       [self takeOutCards:bestCards];
    }

これは悪い習慣のように見えます。

ちなみに、[PlayerInfo インスタンス].cardsPlayed はサーバーからブロードキャストされる変数で、頻繁に変更されます。別のユーザーがどのカードがプレイされるかを待っている間、ユーザーの操作に基づいて変化します。

要するに、ブロードキャストされた変数が来るのを待っている間に何をすべきですか? なにか提案を?ありがとう

4

1 に答える 1

1

アプリでは既にイベント ループが実行されており、ユーザー アクションの間、およびネットワークの新しい状態がチェックされている間、アプリは既にアイドル状態になっているはずです。やりたいことは、条件がトリガーされたときにイベントを生成して、アプリが反応できるようにすることです。

これを行う最も簡単な方法は、状態が発生したときに (アプリ内で) 通知を投稿することです。このようなもの:

// just guessing about your PlayerInfo here, and assuming ARC

@property (nonatomic, strong) NSArray *cardsPlayed;
@synthesize cardsPlayed = _cardsPlayed;

// replace the synthesized setter with one that does the set and checks for
// the condition you care about.  if that condition holds, post a notification
//
- (void)setCardsPlayed:(NSArray *)cardsPlayed {
    _cardsPlayed = cardsPlayed;

    // is the condition about an array that's nil or empty?  guessing 'either' here...
    if (!_cardsPlayed || !_cardsPlayed.count) {
        [[NSNotificationCenter defaultCenter] 
            postNotificationName:@"CardsPlayedDidBecomeEmpty" object:self];
   }
}

次に、条件を気にするオブジェクトを初期化するとき(質問でそのループを提案した場所)...

    [[NSNotificationCenter defaultCenter]
        addObserver:self
           selector:@selector(cardsPlayedEmpty:)
               name:@"CardsPlayedDidBecomeEmpty" object:nil];

これにより、条件が満たされると、cardsPlayedEmpty: が呼び出されます。次のような署名が必要です。

- (void)CardsPlayedDidBecomeEmpty:(NSNotification *)notification {
}

編集- あなたの修正された質問は、サーバーの状態を確認する前に一時停止したいということだと思います. performSelector:withObject:afterDelay: ... を使用してそれを行うことができます。

- (void)getRemoteState {

    NSURLRequest = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        // here, handle the response and check the condition you care about
        // post NSNotification as above here
                       }];
}

// now the code you're trying to write ...

if ([PlayerInfo instance].playingMultiplayer == YES) {

    // give other players a chance to play, then check remote state
    // this will wait 20 seconds before checking
    [self performSelector:@selector(getRemoteState) withObject:nil afterDelay:20.0];
于 2012-11-28T03:26:03.817 に答える