开发者

UIImageView only displaying intermittently

开发者 https://www.devze.com 2023-03-17 12:20 出处:网络
I\'m using the following code to display a page number, when the user switches pages in my iPad app. The number is s开发者_JS百科upposed to show up in a nice transparent gray pane (similar to the \"Bu

I'm using the following code to display a page number, when the user switches pages in my iPad app. The number is s开发者_JS百科upposed to show up in a nice transparent gray pane (similar to the "Build Succeeded" message in XCode). However, the image view only shows up about 5% of the time. (I haven't added the code to put a number in the pane yet). The NSLog() message appears every time. I've also set a breakpoint and stepped through, and the UIImageView code is getting called. Sadly, I can't step into the framework to see what it's doing.

The variables used are all locals or constants, so I doubt it has anything to do with a race condition. Also, I can wait minutes between clicks and not get an image, or press the button rapidly and get multiple stacked images (they're transparent, so it's easy to notice a stack).

I tried running a setNeedsDisplay on self.view after the addSubview: (even though I'm pretty sure addSubview: does it), but that didn't do anything.

Calling displayPageNumber: directly, without threading, doesn't make it appear consistently either.

Any ideas?

#define PageDisplayTime        0.5
#define PageDisplayImageName   @"PageIndicator.png"
#define PageDisplayImage       [UIImage imageNamed: PageDisplayImageName]

...
[NSThread detachNewThreadSelector: @selector(displayPageNumber:) 
          toTarget: self withObject: index];
...

- (void) displayPageNumber: (NSNumber*) _pageIndex
{
  NSLog(@"Page Number: '%d'.", [_pageIndex integerValue] + 1);
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  UIImageView* glassPaneView = [[UIImageView alloc] initWithImage: PageDisplayImage];
  glassPaneView.center = CGPointMake(300.0, 300.0);
  [self.view addSubview: glassPaneView];
  [NSThread sleepForTimeInterval: PageDisplayTime];
  [glassPaneView removeFromSuperview];
  [glassPaneView release];
  [pool release];
}


AFAIK all UI coding must be done on the main thread. doing it on the background thread will at best have unpredictable results, at worse will crash.

Calling the method directly (thus in the main thread) doesn't work because the sleep just stops the current thread, so it is not able to do anything including drawing until you remove the view, thus preventing it from showing.

You have to refactor the method into multiple methods called on the main thread. The first just adds the subview and sets a timer, the timer handling method then removes the subview.


I figured out the issue. In case others run into this, here it is: The addSubview: / removeFromSuperview pair with the sleepForTimeInterval: between them are basically useless. I knew sleeping blocked the thread, but apparently this thread needs to be unblocked to update the view. I assumed (incorrectly it appears) that the view update happened on the main thread.

Here's my replacement solution: unhide the subview in the main thread and call detachNewThreadSelector: with a message that sleeps for X seconds and then hides the subview. And I'm going to add an NSLocked counter that gets incremented on unhide, and decremented in the hider message, but only hides when the counter is down to 0. This will allow repeated activations to extend the duration.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号