UIScrollView setNeedsDisplay не работает или что-то еще? - PullRequest
1 голос
/ 07 февраля 2012

Окончательное решение этой проблемы дано под вопросом

Моя цель - создать средство выбора изображений, которое первоначально создает каждое представление изображения внутри представления с прокруткой, а затем передает ссылку на это представление изображения в метод, который будет асинхронно обновлять imageview.image с соответствующим изображением. .

Это прекрасно работает как есть.

Проблема, с которой я сталкиваюсь, состоит в том, что представление прокрутки показывает только изображения в пакете в конце метода , тогда как я хотел бы, чтобы они печатали по одному при создании (изображение доступно или нет).

Если я касаюсь вида прокрутки для прокрутки , это работает так, как я хочу, но если я вообще не касаюсь, экран остается белым до тех пор, пока все изображения, а не только изображения , закончили загрузку.

Я пробовал размещать setNeedsDisplay везде, для каждого вида, включая self.view, scrollview и каждое отдельное изображение. Что происходит?

- (void)viewDidLoad {
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
     dispatch_async(queue, ^{
          [self setGridView];
     });
}

- (void)setGridView {
    // begin loading images
    NSString * retina = ([[MVProject sharedInstance] settings_retina]) ? @"2" : @"";

    CGRect scrollframe = CGRectMake(0, 0, 300, 275);
    UIScrollView * newscrollview;
    newscrollview = [[UIScrollView alloc] initWithFrame:scrollframe];
    newscrollview.scrollEnabled = YES;
    newscrollview.delegate = self;
    [newscrollview setContentSize:CGSizeMake(300, (((ceilf([[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"Flickr_Dictionary"]] count]/4)) * (58+15)) + 15 + 58 + 15))];
    [picsMVContentCell.contentView addSubview:newscrollview];

    float currentx = 11;
    float currenty = 17;
    NSInteger index = 0;

    for (NSDictionary * d in [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"Flickr_Dictionary"]]) {

        // create button
        UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(currentx, currenty, 58, 58);
        button.imageView.backgroundColor = [UIColor colorWithRed:(241/255.0) green:(241/255.0) blue:(241/255.0) alpha:1];
        button.imageView.contentMode = UIViewContentModeScaleAspectFit;
        button.imageView.layer.cornerRadius = 6;
        button.imageView.layer.masksToBounds = YES;
        button.imageView.accessibilityLabel = [d objectForKey:@"id"];
        button.imageView.accessibilityValue = [d objectForKey:@"full"];
        button.imageView.tag = index++;
        [button addTarget:self action:@selector(imageClick:) forControlEvents:UIControlEventTouchUpInside];

        UIImage * image = [MVImage imageWithImage:[UIImage imageNamed:@""] covertToWidth:58.0f covertToHeight:58.0f];
        [button setImage:image forState:UIControlStateNormal];

        [newscrollview addSubview:button];
        [newscrollview bringSubviewToFront:button];
        [newscrollview setNeedsDisplay];

        // calculate next image view position
        currentx += (button.imageView.frame.size.width+15);
        if (currentx >= 289) {
            currentx = 11;
            currenty += (button.imageView.frame.size.height+15);
        }

        // set image
        NSString * nsuserdefault = [NSString stringWithFormat:@"Settings_SFThumbs%@_%@", retina, [d objectForKey:@"id"]];
        if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]]) {
            MVImage * thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]];
            [button setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
        } else {
            [MVProject asynchronousImageLoad:button.imageView urlpath:[d objectForKey:@"thumb"] nsuserdefaultpath:nsuserdefault];
        }
    }
}

Редактировать 7 февраля 2012 г. 15:26

эти изменения исправили все проблемы, связанные с кодом, приведенным в вопросе

спасибо @Eugene за то, что он указал мне правильное направление

/* ---------- ---------- ---------- ---------- ---------- */

- (void)viewDidLoad {
     [super viewDidLoad];

     [[MVProject sharedInstance] syncLoadSF:0];

    self.newscrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 300, 275)];
    self.newscrollview.scrollEnabled = YES;
    self.newscrollview.delegate = self;
    [self.newscrollview setContentSize:CGSizeMake(300, (((ceilf(([[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"Flickr_Dictionary"]] count]-1)/4)) * (58+15)) + 15 + 58 + 15))];
    [picsMVContentCell.contentView addSubview:self.newscrollview];

    [self setGridView];
}

/* ---------- ---------- ---------- ---------- ---------- */

- (void)setGridView {
    NSString * retina = ([[MVProject sharedInstance] settings_retina]) ? @"2" : @"";
    [self.newscrollview setNeedsDisplay];
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^{
        NSInteger index = 0;
        for (NSDictionary * d in [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"Flickr_Dictionary"]]) {
            // create button
            UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];               
            button.frame = CGRectMake((11 + ((index%4)*(58+15))), (17 + ((floorf(index/4))*(58+15))), 58, 58);
            button.imageView.backgroundColor = [UIColor colorWithRed:(241/255.0) green:(241/255.0) blue:(241/255.0) alpha:1];
            button.imageView.contentMode = UIViewContentModeScaleAspectFit;
            button.imageView.layer.cornerRadius = 3;
            button.imageView.layer.masksToBounds = YES;
            button.imageView.accessibilityLabel = [d objectForKey:@"id"];
            button.imageView.accessibilityValue = [d objectForKey:@"full"];
            button.imageView.tag = index++;
            [button addTarget:self action:@selector(imageClick:) forControlEvents:UIControlEventTouchUpInside];

            dispatch_sync(dispatch_get_main_queue(), ^ {
                [button setImage:[MVImage imageWithImage:[UIImage imageNamed:@""] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
                [self.newscrollview addSubview:button];
                [self.newscrollview bringSubviewToFront:button];
                [self.newscrollview setNeedsDisplay];

                // set image
                NSString * nsuserdefault = [NSString stringWithFormat:@"Settings_SFThumbs%@_%@", retina, [d objectForKey:@"id"]];
                if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]]) {
                    MVImage * thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]];
                    [button setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
                } else {
                    [MVProject asynchronousImageLoad:button.imageView urlpath:[d objectForKey:@"thumb"] nsuserdefaultpath:nsuserdefault];
                }
            });
        }
    });
    [self.newscrollview setNeedsDisplay];
}

Ответы [ 2 ]

2 голосов
/ 07 февраля 2012

Вы не можете работать с рисунком в фоновом потоке.Каждый раз, когда вы добавляете подпредставление, вы должны делать это в главном потоке.Таким образом, для вас спасением будет использование кода рисования в блоке синхронизации, который выполняется в главной очереди

  dispatch_sync(dispatch_get_main_queue(), ^ {
    [newscrollview addSubview:button];
    [newscrollview bringSubviewToFront:button];
    [newscrollview setNeedsDisplay];

    // calculate next image view position
    currentx += (button.imageView.frame.size.width+15);
    if (currentx >= 289) {
      currentx = 11;
      currenty += (button.imageView.frame.size.height+15);
    }

    // set image
    NSString * nsuserdefault = [NSString stringWithFormat:@"Settings_SFThumbs%@_%@", retina, [d objectForKey:@"id"]];
    if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]]) {
      MVImage * thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:nsuserdefault]];
      [button setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f] forState:UIControlStateNormal];
    } else {
      [MVProject asynchronousImageLoad:button.imageView urlpath:[d objectForKey:@"thumb"] nsuserdefaultpath:nsuserdefault];
    }
  });
0 голосов
/ 07 февраля 2012

Ваша проблема в настройке изображений. То, что вы пытаетесь сделать, это добавить все контейнеры изображений в представление прокрутки. Затем, когда изображения готовы, загрузите их в контейнер. Есть 2 способа сделать это.

Прежде всего добавьте все контейнеры в представление прокрутки. (Вы можете захотеть, чтобы какой-нибудь индикатор загрузки или изображение по умолчанию отображало его загрузку)

1) Создайте фоновый поток для подготовки изображений. Когда изображение будет готово, добавьте его в свой контейнер. (Я считаю, что это больше работы и боль)

2) Создайте пользовательский контейнер, и пусть пользовательский контейнер добавит свое собственное изображение, когда его изображение будет готово.

Например, я загружаю изображения с сервера. Поэтому я создал класс AsyncImage, который является пользовательским классом UIImageView. И я создал функцию, которой я отправляю URL изображения, и он обрабатывает все остальное. Он создает NSURLConnection и при загрузке данных вызывает self.image = [UIImage imageWithData:data];

...