2011-12-13 20 views
0

私は、10枚の画像をループしてそれぞれの画像を表示する簡単なテストアプリで遊んでいます。ユーザーがボタンをクリックすると、次の画像が表示されます。私が抱えている問題は、ビューが表示されないことです(画像またはボタン)。ボタン押下句を取り出すと、コードが実行され、最後の画像が表示されます。 continueRunningScriptは最初はYESです。iPhoneに最後の画像しか表示されない

@interface ViewController : UIViewController <UIAlertViewDelegate> 
{ 
    BOOL continueRunningScript; 
    UIButton *wrongButton; 
    UIImageView *imageView; 
} 

// ... 

@end 

@implementation ViewController 

// ... 

- (void) xxx { 

    for (int i = 0; i<10; i++) { 

     while (continueRunningScript == NO) { 
      // Stay here until button is pressed. 
     } 

     UIImage *testImg = ... // code to load the image at index i 

     imageView = [[UIImageView alloc] initWithImage: testImg]; 

     [self.view addSubview:imageView]; 

     wrongButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
     [wrongButton addTarget:self 
         action:@selector(incorrectResultButtonPress:) 
       forControlEvents:UIControlEventTouchUpInside]; 
     [wrongButton setTitle:@"Wrong Result?" forState:UIControlStateNormal]; 
     wrongButton.frame = CGRectMake(80.0, 310.0, 160.0, 40.0); 
     [self.view addSubview:wrongButton]; 

     continueRunningScript = NO; 

     [testImg release]; 
    } 
    [imageView release]; 
    [wrongButton release]; 
} 

// button press handling... 

// UIAlertViewDelegate 
- (void) alertView: (UIAlertView *)actionSheet clickedButtonAtIndex: (NSInteger)buttonIndex { 

    // The user clicked one of the Yes/No buttons 
    if (buttonIndex == 0) // Yes 
    { 
     UIAlertView *thankyouAlert = [[UIAlertView alloc] initWithTitle:@"Thank You" 
                   message:@"Thanks for the feedback!" 
                   delegate:self 
                 cancelButtonTitle:nil 
                 otherButtonTitles:nil]; 
     [thankyouAlert show]; 
     // Call performSelector delegate method of NSObject to call class method dismissAlertView 
     [self performSelector:@selector(dismissAlertView:) withObject:thankyouAlert afterDelay:2]; 
     [thankyouAlert release]; 
     [wrongButton removeFromSuperview]; 
     continueRunningScript = YES; 
    } 
} 

// ... 

@end 
+0

これはループ内で同じ 'imageView'リファレンスを再割り当てするためです。ループを終了すると、常に最後のオブジェクトを指します。 – Joe

+0

将来、投稿する前に、あなたのコードの書式をチェックしてください、私はあなたのためにそれを修正しました。 –

+0

しかし、i = 0のループの最初の繰り返しでは何も表示されません。 –

答えて

1

私はあなたがバックグラウンドスレッドなどでこれをやっていないという前提を立てています。もしあなたがそうであれば、UIKitはメインスレッドからのみ使用できるように設計されていることに注意してください。

while (continueRunningScript == NO) { 
    // Stay here until button is pressed. 
} 

これは、あなたが望むようには機能しません。無限ループに入ります。実行スレッドは、入力イベントを処理するためにこのポイントを過ぎて進まないため、変数は決してYESに設定されることはありません。

メソッドを終了すると、すべてのユーザーインターフェイスコードが実行されることを覚えておく必要があります。純粋なものを取り除くと、追加されたすべての画像がループしていきます。そしてのユーザーインターフェイスが更新されます。そういうわけで、あなたは最後のイメージしか見ることができません。他のイメージも追加されましたが、一番上のもの(最後のイメージ)の下にあります。

ユーザーがボタンをタップするたびに新しい画像を表示したい場合は、現在の画像を追跡するインスタンス変数を用意し、この変数を更新して次の画像。ほとんどすべての状況で、上記のようなビジーなループは間違っています。

また、新しい画像を表示するたびに、新しいUIImageViewを追加する必要はありません。既存のイメージビューのimageプロパティを更新するだけで、表示中のイメージを変更することができます。

+0

ありがとう、ジム。私は確かにこの仕事をする方法を考え直さなければならないでしょう。別の質問は、ループの最初の反復でデバッガのコードをステップ実行しても、ビューに画像とボタンを追加する行が表示されるときに何も表示されないのはなぜですか? –

+0

あなたの関数が返されるまで、iOSは表示を更新することができません。 – Jim

0

imageViewまたはwrongButtonを解放する必要はありません。コントローラーが存在する限り、彼らはおそらく保持したいと思っています。

それ以上に、私はより多くの情報が必要であることを示唆しています。

1

メインスレッドでメソッド 'xxx'が実行されていますか?もしそうなら、犯人は次のとおりです。

while (continueRunningScript == NO) { 
     // Stay here until button is pressed. 
    } 

のiOSは、イベント駆動型アーキテクチャを使用し、あなたがここでやっているように、メインスレッドをブロックするための非常に悪い習慣です。アプリはここで無期限にループし、UIの更新を停止し、ボタンの押下などのイベントには反応しません。これがあなたのビュー、イメージ、ボタンが表示されない理由です。

イベントドリブンアーキテクチャに合わせてアプリケーションを変更する方法について考える必要があります。

+0

ありがとうございます。だから、なぜこれが最初のループの反復後に問題になるのか理解しています。しかし、私はまだ、whileループで動かなくなる前に、画像とボタンが最初の反復で表示されない理由を理解できません)。 –

+0

'addSubview'を呼び出すと、ビューとボタンはすぐには表示されません。 UIは、 'xxx'メソッドが復帰した後にのみ更新されます(実行されることはありません)。これは、実行ループの次の反復のある時点でのみ行われます。 –

0

UIKitは、メインのUI実行ループに戻るときにのみ描画します。あなたのコードは最初の画像の後で、次の画像の前に戻らないので、最初の画像は決して表示されません。

イベントは、メインのUI実行ループでのみ検出/送出されます。コードは最初のボタンハンドラから返されることはないので、その後のボタンイベントは検出されません。

+0

ありがとうございます。メインUI実行ループとは何ですか? viewDidLoad? –

+0

あなたのアプリケーションのコードから戻って、OS、UIKit、Objective Cランタイムは、あなたのアプリケーションを次に呼び出すために何を使用するのですか...表示や入力などのハウスキーピングを行います。例えばそれはviewDidLoadを呼び出すものです。戻ってそれに戻る。 – hotpaw2

関連する問題