Kevin_TA
Kevin_TA

Reputation: 4685

Only Last Image Displayed on iPhone

I'm playing around with a simple test app that just loops through 10 images and displays each one to the view. The next image will be displayed after the user clicks a button. The problem I am having is the view is never appearing (image or button). When I take out the button press clause, the code runs and the last image is displayed. continueRunningScript is initially YES.

@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

Upvotes: 0

Views: 123

Answers (4)

hotpaw2
hotpaw2

Reputation: 70743

UIKit only draws stuff when you return to the main UI run loop. Your code does not return after the first image and before the next, so that first image is never displayed.

Events are also only detected/dispatched in the main UI run loop. Since your code never returns from the first button handler, no subsequent buttons events will be detected.

Upvotes: 0

Robin Summerhill
Robin Summerhill

Reputation: 13675

Is method 'xxx' running on the main thread? If so, the culprit is:

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

iOS uses an event-driven architecture and it is very bad practice to block the main thread like you are doing here. Your app will loop indefinitely here and will stop updating the UI and will not respond to any button presses or other events. This is why your view, image and button are not appearing.

You need to think about how you can modify your app to fit in with the event-driven architecture.

Upvotes: 1

Jim
Jim

Reputation: 73966

I'm making the assumption that you aren't doing this on a background thread or anything. If you are, then you should be aware that UIKit is only designed to be used from the main thread.

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

This will not work the way you want it to. It will enter an infinite loop. The thread of execution will not progress past this point to process any input events, so that variable will never get a chance to be set to YES.

You have to remember that all of the user interface code will run after you exit from your method. If you take the pure out, then you're looping through all the images that are added, then the user interface is updated. That's why you only see the last image - the others were added too, but they are underneath the top-most (last) one.

If you want a new image to be shown every time the user taps a button, then you should have an instance variable that keeps track of which image is the current one, and write a method to update this variable and show the next image. In almost all circumstances, a busy loop like the above is wrong.

Also, you should be aware that you don't have to add a new UIImageView every time you want to display a new image. You can simply update the image property for an existing image view to change which image it is displaying.

Upvotes: 1

Hack Saw
Hack Saw

Reputation: 2781

I don't think you need to release the imageView or wrongButton. They probably want to be retained for as long as the controller exists.

Beyond that guess, I'd suggest we need more information.

Upvotes: 0

Related Questions