【问题标题】:Only Last Image Displayed on iPhoneiPhone 上仅显示最后一张图片
【发布时间】:2011-12-13 19:20:04
【问题描述】:

我正在玩一个简单的测试应用程序,它只循环 10 张图像并将每张图像显示到视图中。用户单击按钮后将显示下一个图像。我遇到的问题是视图永远不会出现(图像或按钮)。当我取出按钮按下子句时,代码运行并显示最后一个图像。 continueRunningScript 最初是 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

【问题讨论】:

  • 这是因为您在循环中重新分配了相同的 imageView 引用。当您完成循环后,它将始终指向最后一个对象。
  • 以后发帖前,请先检查一下你的代码格式,不过我已经给你修好了。
  • 但是为什么在循环的第一次迭代中 i=0 时视图没有显示任何内容?
  • 再次查看您的代码,尝试更改每个图像的框架,看起来它只是将图像放在彼此之上。

标签: iphone objective-c xcode uiimageview uibutton


【解决方案1】:

我假设您没有在后台线程或任何东西上执行此操作。如果你是,那么你应该知道 UIKit 只设计用于在主线程中使用。

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

这不会按您希望的方式工作。它将进入一个无限循环。执行线程不会超过这一点来处理任何输入事件,因此该变量永远不会有机会被设置为YES

您必须记住,所有用户界面代码都将在您退出方法后运行。如果您取出纯图像,那么您将循环浏览所有添加的图像,然后更新用户界面。这就是为什么您只看到最后一张图片的原因 - 其他图片也已添加,但它们位于最上面(最后一张)的下方。

如果您希望每次用户点击按钮时都显示一个新图像,那么您应该有一个实例变量来跟踪哪个图像是当前图像,并编写一个方法来更新此变量并显示下一个图片。在几乎所有情况下,像上面这样的繁忙循环都是错误的。

另外,您应该知道,您不必在每次想要显示新图像时都添加新的UIImageView。您只需更新现有图像视图的 image 属性即可更改它正在显示的图像。

【讨论】:

  • 谢谢,吉姆。我当然必须重新考虑使这项工作发挥作用的方法。另一个问题是,为什么即使我在循环的第一次迭代中单步执行调试器中的代码,当它到达将图像和按钮添加到视图的行时,什么也没有出现?
  • 因为 iOS 在你的函数返回之前不会更新显示。
【解决方案2】:

方法 'xxx' 是否在主线程上运行?如果是这样,罪魁祸首是:

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

iOS 使用事件驱动架构,像您在这里所做的那样阻塞主线程是非常糟糕的做法。您的应用将在此处无限循环并停止更新 UI,并且不会响应任何按钮按下或其他事件。这就是您的视图、图像和按钮没有出现的原因。

您需要考虑如何修改您的应用以适应事件驱动架构。

【讨论】:

  • 谢谢。所以我明白为什么在第一次循环迭代之后这会是一个问题.. 但我仍然不明白为什么在 i=0 时第一次迭代没有显示图像和按钮(在它卡在 while 循环之前)。
  • 调用addSubview时不会立即显示视图和按钮。 UI 仅在 xxx 方法在运行循环的下一次迭代中的某个时间点返回(它永远不会返回)后完全更新。
【解决方案3】:

我认为您不需要释放 imageView 或 wrongButton。只要控制器存在,他们可能希望保留。

除此之外,我建议我们需要更多信息。

【讨论】:

    【解决方案4】:

    UIKit 仅在您返回主 UI 运行循环时才绘制内容。您的代码不会在第一张图片之后和下一张之前返回,因此永远不会显示第一张图片。

    事件也仅在主 UI 运行循环中检测/调度。由于您的代码永远不会从第一个按钮处理程序返回,因此不会检测到后续按钮事件。

    【讨论】:

    • 谢谢。主 UI 运行循环到底是什么? viewDidLoad?
    • 从您的所有应用程序代码中返回,然后操作系统、UIKit 和 Objective C 运行时使用什么来调用您的应用程序……或进行诸如显示和输入之类的内务处理。例如这就是所谓的viewDidLoad。返回以返回它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    相关资源
    最近更新 更多