Delay On IPad When Calling From A Background Thread

I am converting my IPhone app to IPad and I'm having an issue with the conversion. I have a background thread that creates some thumbnails.

The problem seems to be that the app loops though the array and outputs all the items but only the last item seems to be loading with the UIButton text present. There is a 5-15 second delay before all the previous buttons have there text displayed.

UIImage *tmp = [self thumbnailImage:[effect objectAtIndex:0] thumbnailType:@"category"];

for (id effect in effectArray) {

    UIImage *tmp = [self thumbnailImage:[effect objectAtIndex:0] thumbnailType:@"category"];

    dispatch_async(dispatch_get_main_queue(), ^{

        UIView *effectView = [[UIView alloc] initWithFrame:CGRectMake(item_x_axis, current_row_height, item_width, item_height)];

        UIImageView *imagepreview = [[UIImageView alloc] init];
        [imagepreview setFrame:CGRectMake(20, 20, 100, 100)];
        [imagepreview setImage:tmp];
        imagepreview.contentMode = UIViewContentModeScaleAspectFit;
        imagepreview.layer.shadowColor = [UIColor blackColor].CGColor;
        imagepreview.layer.shadowOffset = CGSizeMake(0, 1);
        imagepreview.layer.shadowOpacity = 1;
        imagepreview.layer.shadowRadius = 2.0;
        imagepreview.clipsToBounds = NO;
        [effectView addSubview:imagepreview];

        if([[effect objectAtIndex:3]  isEqualToString:@"iap"]){

            UIImageView *buttonPlus = [[UIImageView alloc] init];
            [buttonPlus setFrame:CGRectMake(54, 66, 23, 23)];
            [buttonPlus setImage:[UIImage imageNamed:@"ButtonPlus.png"]];
            [effectView addSubview:buttonPlus];

        }

        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button addTarget:self action:NSSelectorFromString([effect objectAtIndex:1]) forControlEvents:UIControlEventTouchDown];
        [button setTitle:[effect objectAtIndex:2] forState:UIControlStateNormal];
        button.frame = CGRectMake(0, 0, item_width, item_height);
        button.titleLabel.font = [UIFont systemFontOfSize:11];
        [button setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button.titleLabel setShadowOffset:CGSizeMake(1.0f, 1.0f)];
        [button setTitleEdgeInsets:UIEdgeInsetsMake(120, 0, 0.0, 0.0)];
        [effectView addSubview:button];


        [self.viewScrollCategories addSubview:effectView];

        button = nil;

    });

    if(current_items_per_row < 3){
        current_items_per_row++;
        item_x_axis = item_x_axis + item_width;
    }else {
        current_row_height = current_row_height + item_height;
        current_items_per_row = 1;
        item_x_axis = 0;
    }

}

Any idea how to solve this issue? it seemed to work fine on the IPhone.

EDIT

This is the code that is calling the background thread (shortned)

- (void)imagePickerController:( UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info {


//[self generatingThumbnailMessageShow];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self loadAllEffects];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self generatingThumbnailMessageHide];
    });
});

}

Answers


Well, you are asking for a delay with dispatch_async(dispatch_get_main_queue().... That code means "Please do this whenever you have time, sometime after my current code finishes running." Once you say that, you are basically saying you don't care when this code runs. You hope it will be some time pretty soon, but you've left the runtime to take care of the details.

So perhaps it is this "hope" that is the issue. The architecture of the device processors is different and the threading model for the device might change the way the device responds to having a bunch of these delayed requests piling up.

I'm not at all clear on what you're trying to accomplish in this code (sorry, tl:dr) but the use of delayed performance in the middle of it and your complaint that there is a " 5-15 second delay" seem to go together somehow...

EDIT: OK, I see now that your code is running in the background and you are using dispatch_async to step out to the main thread in order to modify the interface. So perhaps the problem is not in the code you quote, but in the code you are using to manage your background threading in the first place.

ANOTHER EDIT: Just a wild and crazy idea here. If what takes time is the image processing, why don't you do all the image processing and then do your interface updating on the main thread once? What I mean is, you're doing this:

for (id effect in effectArray) {
    UIImage *tmp = // ...
    dispatch_async(dispatch_get_main_queue(), ^{
        // ...
        [imagepreview setImage:tmp];

So you're getting back on the main thread repeatedly each time through the loop. Why not try this:

dispatch_async(dispatch_get_main_queue(), ^{
    for (id effect in effectArray) {
        UIImage *tmp = // ...
        // ...
        [imagepreview setImage:tmp];

Now you're just getting back on the main thread once. There will be a delay while the images process, but then interface should just update, badda bing badda boom (technical programming term).


Need Your Help

Spring & Hibernate @Valid doing nothing

hibernate spring-mvc bean-validation thymeleaf

I have annotated my fields in my model and am using the @Valid annotation on my post controller but it appears to be performing no validation (result.errors is empty)

How can a project be downgraded from .NET 3.5 to .NET 2.0?

.net .net-3.5 .net-2.0 downgrade

If the project is not using any features from .NET 3.5, how do you downgrade to 2.0?

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.