Reputation: 3741
I have an app that loads multiple thumbnail images into a UIScrollVIew. This is a lengthy operation, and so as not to block up the display of the rest of the UI, I am running it in a separate thread. This works fine the first time at application launch, but later a new set of images needs to be loaded into the UIScrollView. When I detach a thread a second time the app crashes (sometimes). Code follows:
// this call is in a separate method
[NSThread detachNewThreadSelector:@selector(addThumbnailsToScrollView) toTarget:self withObject:nil];
// this is the main entry point for the thread
- (void) addThumbnailsToScrollView {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool
// now place all the thumb views as subviews of the scroll view
float xPosition = THUMB_H_PADDING;
int pageIndex = 0;
for (Page *page in self.pages) {
// get the page's bitmap image and scale it to thumbnail size
NSString *name = [page valueForKey:@"pageBackground"];
NSString *basePath = [[NSBundle mainBundle] pathForResource:page.pageBackground ofType:@"jpg" inDirectory:nil];
UIImage *thumbImage = [UIImage imageWithContentsOfFile:basePath];
thumbImage = [thumbImage imageScaledToSize:CGSizeMake(80, 100)];
// create a ThumbImageView for each page and add it to the thumbnailScrollView
if (thumbImage) {
ThumbImageView *thumbView = [[ThumbImageView alloc] initWithImage:thumbImage];
[thumbView setDelegate:self];
[thumbView setImageName:name];
[thumbView setImageSize:CGSizeMake(80, 100)];
[thumbView setPageIndex:pageIndex];
pageIndex ++;
CGRect frame = [thumbView frame];
frame.origin.y = 0;
frame.origin.x = xPosition;
[thumbView setFrame:frame];
[thumbnailPagesScrollView addSubview:thumbView];
[thumbView release];
xPosition += (frame.size.width + THUMB_H_PADDING);
}
}
[self hightlightThumbnailPageAtIndex:0];
[(UIActivityIndicatorView *)[thumbnailPagesScrollView.superview viewWithTag:100] stopAnimating];
[pool release]; // Release the objects in the pool.
}
I thought that a detached thread exits as soon as the main entry routine was completed. Wouldn't the second call to detach a thread be a new thread? Why is the app crashing, but sometimes not?
Thanks
Jk
Upvotes: 2
Views: 1416
Reputation:
You cannot touch UIKit
(meaning UIScrollVIew
) in a secondary thread - you need to reorganize so that the fetch takes place in a secondary thread but you make a NSData object (containing the image binary) available to your primary thread for each thumbnail so that it can do everything related to actually displaying them.
Apple repeatedly warn in documentation that UIKit is not thread-safe.
Upvotes: 2
Reputation: 6769
I would suggest adding the thumbView to the thumbnailPagesScrollView on the main thread rather than a separate thread. There might be issues on the retain count of the object across threads. There is a convenience method performSelectorOnMainThread I think it is to do that. You could pass thumbView to that and then add it to the subview.
Alternatively you could do the whole if statement on the main thread as thats not the thing that will interrupt the user.
Also with your activity indicator this should be stopped on the main thread. Everything UI related should be done on the main thread.
Upvotes: 0