UICollectionView在调用reloadData时不会立即更新,而是在30-60秒后随机更新

时间:2022-04-16 21:07:15

As the title implies, my UICollectionView doesn't update and display the cells immediately after calling reloadData. Instead, it seems to eventually update my collection view after 30-60 seconds. My setup is as follows:

正如标题所示,我的UICollectionView不会在调用reloadData之后立即更新和显示单元格。相反,它似乎最终会在30-60秒后更新我的收藏视图。我的设置如下:

UICollectionView added to view controller in Storyboard with both delegate and dataSource setup for the view controller and standard outlet setup numberOfSectionsInRow & cellForItemAtIndexPath are both implemented and reference the prototyped cell and the imageView inside of it

UICollectionView添加到Storyboard中的视图控制器中,视图控制器的委托和数据源设置以及标准的outlet setup numberOfSectionsInRow和cellForItemAtIndexPath都实现并引用原型单元格和其中的imageView

Here is the code that goes to Twitter, get's a timeline, assigns it to a variable, reloads a table view with the tweets and then goes through the tweets to find photos and reloads the collection view with those items.

这是到Twitter的代码,get有一个时间轴,将它分配给一个变量,用tweet重新加载一个表视图,然后遍历tweet来查找照片,然后用这些项重新加载集合视图。

Even if I comment out the code to display the image, it still doesn't change anything.

即使我注释掉显示图像的代码,它也不会改变任何东西。

SLRequest *timelineRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:timelineURL parameters:timelineParams];
[timelineRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
    if(responseData) {
        JSONDecoder *decoder = [[JSONDecoder alloc] init];

        NSArray *timeline = [decoder objectWithData:responseData];

        [self setTwitterTableData:timeline];

        for(NSDictionary *tweet in [self twitterTableData]) {
            if(![tweet valueForKeyPath:@"entities.media"]) { continue; }

            for(NSDictionary *photo in [[tweet objectForKey:@"entities"] objectForKey:@"media"]) {
                [[self photoStreamArray] addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                                                    [photo objectForKey:@"media_url"], @"url",
                                                    [NSValue valueWithCGSize:CGSizeMake([[photo valueForKeyPath:@"sizes.large.w"] floatValue], [[photo valueForKeyPath:@"sizes.large.h"] floatValue])], @"size"
                                                    , nil]];
            }
        }

        [[self photoStreamCollectionView] reloadData];
    }
}];

3 个解决方案

#1


41  

This is a classic symptom of calling UIKit methods from a background thread. If you view the -[SLRequest performRequestWithHandler:] documentation, it says the handler makes no guarantee of which thread it will be run on.

这是从后台线程调用UIKit方法的典型症状。如果您查看-[SLRequest performRequestWithHandler:]文档,它说处理程序不能保证它将运行在哪个线程上。

Wrap your call to reloadData in a block and pass this to dispatch_async(); also pass dispatch_get_main_queue() as the queue argument.

将对reloadData的调用封装到一个块中,并将其传递给dispatch_async();还将dispatch_get_main_queue()传递为队列参数。

#2


8  

You need to dispatch the update to the main thread:

您需要将更新发送到主线程:

 dispatch_async(dispatch_get_main_queue(), ^{
    [self.photoStreamCollectionView reloadData];
  });

or in Swift:

或者在迅速:

dispatch_async(dispatch_get_main_queue(), {
    self.photoStreamCollectionView.reloadData()
})

#3


3  

Apple say:You should not call this method in the middle of animation blocks where items are being inserted or deleted. Insertions and deletions automatically cause the table’s data to be updated appropriately.

苹果说:不应该在插入或删除项目的动画块中间调用这个方法。插入和删除会自动导致适当地更新表的数据。

In face: You should not call this method in the middle of any animation (include UICollectionView in the scrolling).

在任何动画中,你都不应该调用这个方法(在滚动中包含UICollectionView)。

so, you can:

所以,你可以:

[self.collectionView setContentOffset:CGPointZero animated:NO];
[self.collectionView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

or mark sure not any animation, and then call reloadData; or

或不标记任何动画,然后调用reloadData;或

[self.collectionView performBatchUpdates:^{
//insert, delete, reload, or move operations
} completion:nil];

#1


41  

This is a classic symptom of calling UIKit methods from a background thread. If you view the -[SLRequest performRequestWithHandler:] documentation, it says the handler makes no guarantee of which thread it will be run on.

这是从后台线程调用UIKit方法的典型症状。如果您查看-[SLRequest performRequestWithHandler:]文档,它说处理程序不能保证它将运行在哪个线程上。

Wrap your call to reloadData in a block and pass this to dispatch_async(); also pass dispatch_get_main_queue() as the queue argument.

将对reloadData的调用封装到一个块中,并将其传递给dispatch_async();还将dispatch_get_main_queue()传递为队列参数。

#2


8  

You need to dispatch the update to the main thread:

您需要将更新发送到主线程:

 dispatch_async(dispatch_get_main_queue(), ^{
    [self.photoStreamCollectionView reloadData];
  });

or in Swift:

或者在迅速:

dispatch_async(dispatch_get_main_queue(), {
    self.photoStreamCollectionView.reloadData()
})

#3


3  

Apple say:You should not call this method in the middle of animation blocks where items are being inserted or deleted. Insertions and deletions automatically cause the table’s data to be updated appropriately.

苹果说:不应该在插入或删除项目的动画块中间调用这个方法。插入和删除会自动导致适当地更新表的数据。

In face: You should not call this method in the middle of any animation (include UICollectionView in the scrolling).

在任何动画中,你都不应该调用这个方法(在滚动中包含UICollectionView)。

so, you can:

所以,你可以:

[self.collectionView setContentOffset:CGPointZero animated:NO];
[self.collectionView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

or mark sure not any animation, and then call reloadData; or

或不标记任何动画,然后调用reloadData;或

[self.collectionView performBatchUpdates:^{
//insert, delete, reload, or move operations
} completion:nil];