Ios 无法更改UICollectionView上的backgroundView属性

Ios 无法更改UICollectionView上的backgroundView属性,ios,uicollectionview,Ios,Uicollectionview,我有一个UICollectionView,我正在尝试根据CollectionView中是否有任何数据,使用backgroundView属性设置背景图像。我有一个导航,可以更改数据并重新加载集合视图(调用[self.collectionView reloadData])。出于某种原因,我得到了非常奇怪的结果。首先,有时当我设置属性时,它会出现在collectionView单元格的顶部,并将其遮挡。其次,当我试图更改属性时,它不会在屏幕上更改。 这简直快把我逼疯了!实施起来似乎很简单 所以在代码中。

我有一个
UICollectionView
,我正在尝试根据CollectionView中是否有任何数据,使用backgroundView属性设置背景图像。我有一个导航,可以更改数据并重新加载集合视图(调用
[self.collectionView reloadData]
)。出于某种原因,我得到了非常奇怪的结果。首先,有时当我设置属性时,它会出现在collectionView单元格的顶部,并将其遮挡。其次,当我试图更改属性时,它不会在屏幕上更改。 这简直快把我逼疯了!实施起来似乎很简单

所以在代码中。在
UICollectionViewController

- (void)viewDidLoad {
[self loadSections];
[self setupBackgroundView;
}
Load sections方法仅加载我用于collection视图的数据,然后该方法还调用一个方法来设置背景视图,该背景视图根据是否存在以下数据来决定要添加的视图:

- (void)loadSections {
[self loadPictures];
[self setupBackgroundImage];
}

- (void)setupBackgroundImage {
if ([self.sections count] == 0 || !self.sections) {
    self.collectionView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TakePhoto"]];
}
else {
    self.collectionView.backgroundView = nil;
}
}
现在,当视图首次加载时,如果没有数据,因此没有用于显示背景图像的单元格,则会正确显示背景图像。然后我更改了数据,现在我有一些单元格要显示,setupBackgroundImage被调用,我可以验证backgroundImage属性是否设置为nil(我甚至在这里中断并检查了值,它是nil)。但背景图像仍然可见

此外,如果我将nil更改为另一个图像,则不会显示此新图像

更奇怪的是。如果我显示了一些单元格并设置了背景图像,那么该图像将整齐地显示在单元格后面。若我用一个新的数据集重新加载数据,那个么图像就会显示在单元格前面,使单元格模糊。我不知道这是怎么发生的,因为当时背景视图应该在所有其他视图后面

有人知道为什么会这样吗。它在哪里被缓存了吗?还是我只是在做傻事?我在这里完全不知所措-在这方面花费的时间比编写它使用的自定义布局要多

试试这个

self.collectionView.backgroundView =[[UIView alloc]initWithFrame:self.collectionView.bounds]; 
UIImageView *imgVW=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"TakePhoto"]];
[self.collectionView.backgroundView addSubView:imgVW];

好的,我找到了解决我具体问题的方法,尽管我仍然不明白为什么我会出现问题中提到的奇怪行为,至少这样可以让我改变背景图像

基本上,我创建一个属性来保存
UIImageView
,然后将
UICollectionView
设置为此属性。然后,我可以通过已保存的属性在图像视图中更改图像

- (void)viewDidLoad {
    [self loadSections];
    self.backgroundImageView = [[UIImageView alloc] initWithImage:nil];
    self.backgroundImageView.contentMode = UIViewContentModeCenter;
    self.collectionView.backgroundView = self.backgroundImageView;
}

- (void)setupBackgroundImage {
    if ([self.sections count] == 0 || !self.sections) {
        self.backgroundImageView.image = [UIImage imageNamed:@"TakePhoto"];
    }
    else {
            self.backgroundImageView.image = nil;
    }
}

- (void)loadSections {
    [self loadPictures];
    [self setupBackgroundImage];
}
其中,
self.backgroundImageView
是我为保留对背景视图的引用而定义的属性


如果有人对问题中提到的奇怪行为有任何见解,我真的很想听听

我真的不知道这是否相关,但我在长时间搜索后发现了这一点。希望这能节省一些时间

与UICollectionView一样,UITableView具有在自动布局之前生成的背景视图。如果使用自动布局,则应确保背景视图具有框架。否则它就会消失。在单元格子类中,可以执行以下操作:

    -(void)setBackgroundView:(UIView *)backgroundView
{
    super.backgroundView = backgroundView;
    self.backgroundView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.backgroundView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero];
}

正如这篇文章所指出的

当cmd+单击UICollectionViewCell类时,您可能会有一个痛苦的阅读


// The background view is a subview behind all other views.
// If selectedBackgroundView is different than backgroundView, it will be placed above the background view and animated in on selection.
@property (nonatomic, strong, nullable) UIView *backgroundView;
新的插入到旧的下面。我刚刚花了最后一个小时调试和咒骂,试图找出什么不起作用


只需使用removeFromSuperview

好的,我需要有两个不同的视图并在它们之间切换。。。看起来backgroundView很不稳定,但我还是设法获得了这样的功能

backgroundLoadingView?.isHidden = true
noItemsBackgroundView?.isHidden = false
backgroundView = noItemsBackgroundView
这意味着我必须隐藏/显示所需视图,并将所需视图指定给属性

切换到loadingView的步骤

    backgroundLoadingView?.isHidden = false
    noItemsBackgroundView?.isHidden = true
    backgroundView = backgroundLoadingView
并将其完全隐藏起来

backgroundView?.isHidden = true

alt.您可以在一个视图中拥有不同的视图,并将其指定给背景视图,然后切换其子视图

是否有可能创建并添加多个
UICollectionViews
作为子视图?这可以解释你看到的行为。谢谢你的评论bobnoble。我还想知道这是否会发生。据我所知,从代码检查和运行Instruments分配工具来看,没有,只有一个UICollectionView。setupBackgroundImage有时会在主线程以外的线程上被调用吗?collection view是UIScrollView的一个子类。UIScrollView的要点是根据滚动动态转换子视图的帧位置。因此,backgroundView的预期含义和行为是不明确的(它是在scrollview内容平面上还是在与scrollview本身的背景相对应的视图上?),UIView的正常backgroundView属性不受支持。此外,出于性能原因,苹果公司不希望鼓励将“静态”背景内容设置为显示在内容平面上的滚动视图下。如果您特别希望,您可以设置静态背景图像,通过添加视图并确保其位置在每次调用scrollViewDidScroll时都会更新,从而相对于scrollView内容偏移量保持固定:您确定这不是您的背景图像格式问题吗?当我试图建立大学背景图片时,我也遇到了同样的问题。在我改为使用其他png格式的图片后,效果很好。self.CollectionView.backgroundView=[[UIImageVIew alloc]initWithImage:[UIImageName:@“newPic”];self.backgroundView?.removeFromSuperview()不适合我,即使在调用removeFromSuperview()时,旧视图仍然存在