[英]UICollectionView Reload Data Not Working to update CollectionView
UPDATTE:
我忘記提到CollectionView位於Split View Controller的右側,而在左側,我有tableView。 當選擇一行時,我傳遞一個新的FEED ADDRESS並讓它在右側運行refreshFeed方法。
我有一個集合視圖,用於解析XML中的數據。 當按下某個按鈕時,我希望它清除CollectionView,並從不同的XML加載數據,這兩個XML都在線。 我使用ASIHTTPRequest和GDATAXML類來幫助我解決這個問題。 這是我的代碼。 我可以通過日志驗證NSMutableArray已被清除,並成功填充了不同的XML,但reloadData永遠不會發生,因為第二次不會調用cellForItem。 我搞砸了哪里?
@interface RightViewController ()
@property (nonatomic, strong) IBOutlet UICollectionView *collectionView;
@end
@implementation RightViewController
@synthesize allEntries = _allEntries;
@synthesize feeds = _feeds;
@synthesize queue = _queue;
@synthesize webViewController = _webViewController;
@synthesize activity;
@synthesize webViewController2 = _webViewController2;
@synthesize nameit2;
@synthesize nowplaying;
@synthesize entryofmp3 = _entryofmp3;
@synthesize nameit;
@synthesize progress;
@synthesize lastSelection;
@synthesize backgroundTaskIdentifier, theurl;
@synthesize thetable, thepath, downloadlabel, receivedData, progressbutton;
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [_allEntries count];
}
- (void)loadFirstTime {
self.allEntries = [NSMutableArray array];
self.queue = [[NSOperationQueue alloc] init];
if (_feedAddress == nil) {
_feedAddress = @"http://www.316apps.com/AIMAPPLETV/AIMSeries.xml";
}
self.feeds = [NSArray arrayWithObjects:_feedAddress,
nil];
for (NSString *feed in _feeds) {
NSLog(@"Running Fine");
NSURL *url = [NSURL URLWithString:feed];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
NSLog(@"Still Good");
//[self.collectionView reloadData];
}
-(void)changeFeed {
[_allEntries removeAllObjects];
_feedAddress = @"http://www.316apps.com/AIMAPPLETV/AIMCON.xml";
[self loadFirstTime];
// self.queue = nil;
//_request.delegate = nil;
// _request.delegate = nil;
// [_collectionView reloadData];
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// [self performSegueWithIdentifier:@"playMovies" sender:self];
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
NSString *wifiStreamAddress = entry.articleUrl;
AVPlayer *player = [[AVPlayer alloc] initWithURL: [NSURL URLWithString: wifiStreamAddress] ];
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.player = player;
// Keep pointers to player and controller
self.player = player;
self.playerViewController = playerViewController;
[self presentViewController: playerViewController animated: true completion: ^{
[self.player play];
}];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:@"playMovies"])
{
PlayMovies *userViewController = [segue destinationViewController];
//if you need to pass data to the next controller do it here
}
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
static NSString *cellIdentifier = @"cvCell";
CVCell *cell = (CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
[cell.theimage setImageWithURL:[NSURL URLWithString:entry.articleImage] placeholderImage:[UIImage imageNamed:@"icon@2x.png"]];
cell.theimage.adjustsImageWhenAncestorFocused = YES;
cell.theimage.clipsToBounds = false;
return cell;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.allEntries = [NSMutableArray array];
self.queue = [[NSOperationQueue alloc] init];
[self loadFirstTime];
}
-(void) viewWillAppear:(BOOL)animated {
}
- (void)parseRss:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSArray *channels = [rootElement elementsForName:@"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:@"title"];
NSArray *items = [channel elementsForName:@"item"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [item valueForChild:@"title"];
NSString *articleUrl = [[[[item elementsForName: @"enclosure"] lastObject] attributeForName: @"url"] stringValue];
NSString *articleDateString = [item valueForChild:@"pubDate"];
NSString *picture = [[[[item elementsForName: @"itunes:image"] lastObject] attributeForName: @"href"] stringValue];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
RSSEntry *entry = [[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:articleTitle
articleUrl:articleUrl
articleDate:articleDate
articleImage:picture];
[entries addObject:entry];
NSLog(@"%@", entries);
}
}
[self.collectionView reloadData];
}
- (void)parseFeed:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
if ([rootElement.name compare:@"rss"] == NSOrderedSame) {
[self parseRss:rootElement entries:entries];
} else if ([rootElement.name compare:@"feed"] == NSOrderedSame) {
// [self parseAtom:rootElement entries:entries];
} else {
NSLog(@"Unsupported root element: %@", rootElement.name);
}
}
- (void)requestFinished:(ASIHTTPRequest *)request {
NSLog(@"Request Finished");
[_queue addOperationWithBlock:^{
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:[request responseData]
options:0 error:&error];
if (doc == nil) {
NSLog(@"Failed to parse %@", request.url);
} else {
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
[_allEntries insertObject:entry atIndex:insertIdx];
}
}];
}
}];
}
- (void)requestFailed:(ASIHTTPRequest *)request {
NSError *error = [request error];
NSLog(@"Error: %@", error);
[self loadFirstTime];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
第二次更新:
我慢慢地到了某個地方。 認為這是因為我沒有設置Segue。 我將左側CellView的一個segue吸收到Collection View的View Controller並設置為ShowDetail,並將其命名。 然后在LeftViewController中:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1) {
[self performSegueWithIdentifier:@"doingIt" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:@"doingIt"])
{
self.rightViewController = [[RightViewController alloc] init];
[self.rightViewController refresheyc];
//if you need to pass data to the next controller do it here
}
}
在RightViewController我有:
-(void)refresheyc {
NSLog(@"This Sucks");
[self.allEntries removeAllObjects];
[self.collectionView reloadData];
self.allEntries = nil;
self.queue = nil;
self.allEntries = [NSMutableArray array];
self.queue = [[NSOperationQueue alloc] init];
self.feeds = [NSArray arrayWithObjects:@"http://www.316apps.com/AIMAPPLETV/AIMCON.xml",
nil];
for (NSString *feed in _feeds) {
NSURL *url = [NSURL URLWithString:feed];
NSLog(@"URL%@", url);
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
}
CollectionView中的Cells立即消失,但幾秒鍾之后,它們都回來了,完全沒有改變XML,但我明白了:
2016-01-09 14:37:31.542 AIM-TV[7965:522091] This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.
Stack:(
0 CoreFoundation 0x0000000109fa6ff5 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010d45cdeb objc_exception_throw + 48
2 CoreFoundation 0x0000000109fa6f2d +[NSException raise:format:] + 205
3 Foundation 0x000000010aa96341 _AssertAutolayoutOnMainThreadOnly + 79
4 Foundation 0x000000010a8f6d6e -[NSISEngine withBehaviors:performModifications:] + 31
5 UIKit 0x000000010c804eb8 -[UIView(AdditionalLayoutSupport) _withAutomaticEngineOptimizationDisabledIfEngineExists:] + 58
6 UIKit 0x000000010c804854 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 646
7 UIKit 0x000000010c804ec1 -[UIView(AdditionalLayoutSupport) _withAutomaticEngineOptimizationDisabledIfEngineExists:] + 67
8 UIKit 0x000000010c804589 -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 242
9 UIKit 0x000000010c80405d -[UIView(AdditionalLayoutSupport) _initializeHostedLayoutEngine] + 649
10 UIKit 0x000000010c7f652a -[UIView(UIConstraintBasedLayout) _initializeLayoutEngine] + 152
11 UIKit 0x000000010c7f652a -[UIView(UIConstraintBasedLayout) _initializeLayoutEngine] + 152
12 UIKit 0x000000010c804e24 -[UIView(AdditionalLayoutSupport) _layoutEngineCreateIfNecessary] + 62
13 UIKit 0x000000010c7f732b -[UIView(UIConstraintBasedLayout) _tryToAddConstraint:roundingAdjustment:mutuallyExclusiveConstraints:] + 126
14 UIKit 0x000000010c7f75ef -[UIView(UIConstraintBasedLayout) _addConstraint:] + 274
15 UIKit 0x000000010c7fd247 -[UIView(UIConstraintBasedLayout) _updateContentSizeConstraints] + 779
16 UIKit 0x000000010c806270 -[UIView(AdditionalLayoutSupport) updateConstraints] + 224
17 UIKit 0x000000010c80559b -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:forSecondPass:] + 550
18 UIKit 0x000000010c805866 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:forSecondPass:] + 198
19 UIKit 0x000000010c8054aa -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:forSecondPass:] + 309
20 UIKit 0x000000010c805866 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:forSecondPass:] + 198
21 UIKit 0x000000010c8054aa -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:forSecondPass:] + 309
22 UIKit 0x000000010c804ec1 -[UIView(AdditionalLayoutSupport) _withAutomaticEngineOptimizationDisabledIfEngineExists:] + 67
23 UIKit 0x000000010c80583a -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:forSecondPass:] + 154
24 UIKit 0x000000010c805e9e __60-[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded]_block_invoke + 98
25 UIKit
您無法在后台線程中更新UI元素。 [self.collectionView reloadData]是從parseRss調用的,parseRss本身稱為表單parseFeed,由_queue上的操作調用。 如果_queue沒有碰巧被主線程處理,你將在collectionView中獲得不可預測的結果,並且更有可能崩潰。
您應該將對[self.collectionView reloadData]的調用發送到主線程。
dispatch_async(dispatch_get_main_queue(), { self.collectionView.reloadData() })
(這是Swift語法,我不熟悉Obj-C,抱歉)
問題真的很奇怪,但它在某種程度上對我有用,我在動畫塊中添加了更新約束代碼,
UIView.animate(withDuration: 0.5, animations: {() -> Void in
//update constraints here
self.view.layoutIfNeeded()
self.collectionView.layoutIfNeeded()
})
self.collectionView.reloadData()
正如Alain的回答所述 ,這是因為UI更改需要由主線程處理。 我看到問題是使用Objective C發布的,並在Swift中回答,所以我認為我會發布Objective C版本以防任何人需要它。
dispatch_async(dispatch_get_main_queue(), ^ {
[self.collectionView reloadData];
});
除了@Alain T.提到wrt dspatching對reloadData()的調用之外,請確保你的項目高度設置得恰當。 當itemHeight為零或某個非常大的值時,您可能會看到按預期調用的collectionView(numberOfItemsInSection) and numberOfSections()
,而不是您的collectionView( cellForItemAt)
。
因此,請確保通過調用設置項目高度:
collectionView(collectionView, layout, sizeForItemAt)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.