1

この問題の最終的な解決策は、質問の下に記載されています

私の目標は、最初にスクロール ビュー内に各画像ビューを作成する画像ピッカーを作成し、その画像ビューの参照を、適切な画像で imageview.image を非同期に更新するメソッドに渡すことです。

これはそのままでうまく機能します。

私が遭遇する問題は、スクロールビューがメソッドの最後にバッチで画像ビューのみを表示するのに対し、作成時に1つずつ印刷したいということです(画像が利用可能かどうか)。

scroll view をタッチして scroll すると、思い通りに動作しますが、まったくタッチしないと、画像ビューだけでなくすべての画像の読み込みが完了するまで画面が白いままになります。

self.view、scrollview、および個々の imageview を含むすべてのビューに対して、setNeedsDisplay をどこにでも配置しようとしました。どうしたの?

- (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];
        }
    }
}

2012 年 2 月 7 日 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];
}
4

2 に答える 2

2

バックグラウンド スレッドで描画を行うことはできません。サブビューを追加するたびに、メインスレッドでこれを行う必要があります。したがって、あなたにとっての救いは、メイン キューで実行される同期ブロックで描画コードを使用することです。

  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];
    }
  });
于 2012-02-07T18:24:53.097 に答える
0

あなたが抱えている問題は、画像の設定にあります。あなたがやろうとしていることは、すべての画像コンテナをスクロールビューに追加することです。次に、画像の準備ができたら、それらをコンテナにロードします。これを行うには2つの方法があります。

まず、すべてのコンテナをスクロールビューに追加します。(読み込みインジケーターまたはデフォルトの画像に読み込みを表示したい場合があります)

1)画像を準備するためのバックグラウンドスレッドを作成します。画像の準備ができたら、コンテナに追加します。(私はこの方法がより多くの仕事であり、ちょっと苦痛だと思います)

2)カスタムコンテナを作成し、イメージの準備ができたらカスタムコンテナに独自のイメージを追加させます。

たとえば、サーバーから画像を読み込んでいます。そこで、UIImageViewのカスタムクラスであるAsyncImageクラスを作成しました。そして、画像のURLを送信する関数を作成し、残りを処理します。NSURLConnectionを作成し、データがロードされると呼び出しますself.image = [UIImage imageWithData:data];

于 2012-02-07T18:41:59.343 に答える