【问题标题】:Asynchronus for loop in iphoneiphone中的异步for循环
【发布时间】:2013-08-27 09:28:02
【问题描述】:

for循环看起来像这样,我在视图中写的确实加载了,所以加载这个页面需要更多时间。

for (int i=3; i<[[[[dataDict objectForKey:@"rss"]objectForKey:@"channel"]objectForKey:@"item"]count]; i++)
{


    if (i%3==0)
    {
        x=0;
        y++;
    }

    view=[[UIView alloc]initWithFrame:CGRectMake((x*250)+5, (y*404)+6, 244, 400)];
    [view setBackgroundColor:[UIColor whiteColor]];
    view.layer.borderColor=[[UIColor whiteColor]CGColor];
    view.layer.borderWidth=1.0;
    view.layer.cornerRadius = 5;
    view.layer.masksToBounds = YES;
    [scroller addSubview:view];

titlelabel=[[UILabel alloc]initWithFrame:CGRectMake(10, 10, 230, 20)];
    [titlelabel setText:[[[[[[dataDict objectForKey:@"rss"]objectForKey:@"channel"]objectForKey:@"item"]objectAtIndex:i]objectForKey:@"title"]objectForKey:@"text"]];
    [titlelabel setNumberOfLines:0];
    titlelabel.font=[UIFont boldSystemFontOfSize:15.0f];




    [titlelabel setBackgroundColor:[UIColor clearColor]];
    [titlelabel sizeToFit];
    [view addSubview:titlelabel];

    datelabel=[[UILabel alloc]initWithFrame:CGRectMake(10, 62, 190, 20)];
    [datelabel setText:[[[[[[dataDict objectForKey:@"rss"]objectForKey:@"channel"]objectForKey:@"item"]objectAtIndex:i]objectForKey:@"title"]objectForKey:@"text"]];
    [datelabel setNumberOfLines:0];
    datelabel.font=[UIFont fontWithName:@"arial" size:12.0f];
    [datelabel setBackgroundColor:[UIColor clearColor]];
    [datelabel sizeToFit];
    [view addSubview:datelabel];

    NSData *data=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:[[[[[[[dataDict objectForKey:@"rss"]objectForKey:@"channel"]objectForKey:@"item"]objectAtIndex:i]objectForKey:@"image"]objectForKey:@"text"]stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]];
    NSLog(@"data= %@",data);
    if (data==NULL ||[[[[[[[dataDict objectForKey:@"rss"]objectForKey:@"channel"]objectForKey:@"item"]objectAtIndex:i]objectForKey:@"image"]objectForKey:@"text"] isEqualToString:@""])
    {
        textview=[[UITextView alloc]initWithFrame:CGRectMake(2,80, 238, 386)];
        [textview setText:[[[[[[dataDict objectForKey:@"rss"]objectForKey:@"channel"]objectForKey:@"item"]objectAtIndex:i]objectForKey:@"title"]objectForKey:@"text"]];
        [textview setFont:[UIFont fontWithName:@"ArialMT" size:14]];
        [textview setDelegate:self];
        [view addSubview:textview];
    }
    else
    {
        imageview=[[UIImageView alloc]initWithFrame:CGRectMake(7, 80, 230, 150)];
        [imageview setImage:[UIImage imageWithData:data]];
        [view addSubview:imageview];

        textview=[[UITextView alloc]initWithFrame:CGRectMake(5, 240, 238, 200)];
        [textview setText:[[[[[[dataDict objectForKey:@"rss"]objectForKey:@"channel"]objectForKey:@"item"]objectAtIndex:i]objectForKey:@"title"]objectForKey:@"text"]];
        [textview setFont:[UIFont fontWithName:@"ArialMT" size:14]];
        [textview setDelegate:self];
        [view addSubview:textview];
    }

}

这里让我感到问题的是每次都从服务器获取的图像,所以这会变慢,请建议如何使它像延迟加载一样......

提前致谢

【问题讨论】:

  • rssItems 中通常有多少项?
  • @James 它的动态,也可以是 sumtime 10 sumtime 50 ...
  • @Bala async 方法会在后台执行,我知道,但我只在 for 循环中将视图添加到滚动条,完成后它将如何 1 比 1 工作?
  • 我很惊讶它这么慢的项目数量。您是否考虑过使用 UICollectionView 代替?您将能够创建类似的网格布局,而不必担心自己加载数据——这与使用 UITableView 非常相似。

标签: iphone objective-c ipad ios5 ios6


【解决方案1】:

在我看来,UICollectionView 应该是显示此类数据的更好选择, 但它与ios5不兼容。

如果您需要 ios 5 兼容性,请查看该答案:https://stackoverflow.com/a/16039194/2707614

最后,为了回答你的问题,你可以尝试使用Grand Central Dispatch 如解释here

应该是这样的(我没有电脑可以测试):

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

 dispatch_async(queue, ^{
for (int i=3; i<[[[self rssParser]rssItems]count]; i++)
    // for (int i=3; i<[titlearray count]; i++)
{
    if (i%3==0)
    {
        x=0;
        y++;
    }

    view=[[UIView alloc]initWithFrame:CGRectMake((x*250)+10, (y*306)+105, 244, 300)];
    [view setBackgroundColor:[UIColor whiteColor]];
    view.layer.borderColor=[[UIColor whiteColor]CGColor];
    view.layer.borderWidth=1.0;
    view.layer.cornerRadius = 5;
    view.layer.masksToBounds = YES;



    titlelabel=[[UILabel alloc]initWithFrame:CGRectMake(10, 10, 230, 20)];
    [titlelabel setText:[[[[self rssParser]rssItems]objectAtIndex:i-1]title]];
    [titlelabel setNumberOfLines:0];
    titlelabel.font=[UIFont boldSystemFontOfSize:14.0f];

    [titlelabel setBackgroundColor:[UIColor clearColor]];
    [titlelabel sizeToFit];


    datelabel=[[UILabel alloc]initWithFrame:CGRectMake(10, 62, 190, 20)];
    [datelabel setText:[[[[self rssParser]rssItems]objectAtIndex:i-1]pubDate]];
    [datelabel setNumberOfLines:0];
    datelabel.font=[UIFont fontWithName:@"arial" size:10.0f];
    [datelabel setBackgroundColor:[UIColor clearColor]];
    [datelabel sizeToFit];

    x++;

    dispatch_sync(dispatch_get_main_queue(), ^{
        [scroller addSubview:view];
        [view addSubview:titlelabel];
        [view addSubview:datelabel];
    });

}
});

【讨论】:

  • 您不应该在后台队列中处理 UI 对象。这通常包括创建它们(除非在最近的版本中发生了变化)。另外,请注意,这样做假定rssParser 等都是线程安全的......
  • 我曾经在后台队列中创建 ui 对象并在主线程上调用“显示相关”方法没有问题,但我很想知道为什么只创建对象是不好的。
  • 来自文档:注意: 在大多数情况下,UIKit 类只能在应用程序的主线程中使用。对于从 UIResponder 派生的类或涉及以任何方式操作应用程序的用户界面的类尤其如此。 IE。它只是巧合。
  • 感谢您的回答,这是我阅读过的文档的一部分。但对我来说,这并不意味着你不能在后台线程中创建对象......我认为这不是巧合,它之所以有效,是因为在未添加视图之前不会调用 drawRect 方法。我想我会为此创建一个关于 SO 的问题,因为我不确定。谢谢,这将是我的第一个!
  • 对你有用没关系;它的工作原理只是巧合。它被明确记录为避免意味着它可能在任何给定的软件更新或特定的硬件配置(或系统配置 - 例如本地化可能对 UITextField 的行为变化产生重大影响)后无法工作.
猜你喜欢
  • 2017-05-19
  • 2019-02-15
  • 2014-02-06
  • 1970-01-01
  • 2015-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多