'cellForItemAtIndexPath' 中的自定义单元格初始化导致堆叠单元格堆叠视图
Custom Cell init in 'cellForItemAtIndexPath' causing stacked cell to stack views
我使用这个函数创建了一个单元格:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
BOOL isFocusOn = [_userDefault boolForKey:@"mixFocusOn"];
CDCChannelStrip *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
if (isFocusOn == TRUE) {
NSNumber *setChan = [self.focusChannels objectAtIndex:indexPath.section];
NSInteger chanInt = [setChan intValue];
[cell initData:(chanInt)];
[self getParameters:(setChan)];
} else {
NSInteger chanInt = indexPath.section;
NSNumber *chanNum = [NSNumber numberWithInt:chanInt]; // doesnt matter
[cell initData:(chanInt)]; // init
[self getParameters:(chanNum)]; // params
}
[self.mixMonitorView setChannelsStripToType:(cell)];
cell.clipsToBounds = YES;
return cell;
}
有问题的函数是 initData
,它看起来像这样:
- (void)initData:(NSInteger)channel {
self.isBus = false;
self.isSendChan = false;
self.recallSafeFade = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"recallSafe"]];
self.recallSafeFade.y = 80;
[self.recallSafeFade setUserInteractionEnabled:YES];
self.recallSafeHead = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"recallSafeHeadamp"]];
[self.recallSafeHead setUserInteractionEnabled:NO];
self.recallSafePan = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"recallSafePan"]];
self.recallSafePan.y = 768 - 141;
[self.recallSafePan setUserInteractionEnabled:YES];
self.channelNumber = channel;
[self setClipsToBounds:NO];
_background = [[UIView alloc] initWithFrame:CGRectMake(0, 80, 122, 547)];
[_background setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"singleFader"]]];
[self addSubview:_background];
[self addChannelName];
[self addInput];
[self addPan];
[self addOn];
[self addMeter];
[self addFader];
}
所以我遇到的问题是,我需要调用此函数来设置我的自定义单元格,以按照我需要的方式查看和运行。但是,每次由于状态更改我在 collectionview 上调用重新加载时,它会将新视图分层放置在旧视图的顶部(由于重复出现 imageview alloc)
那么我如何才能自动将此功能应用于每个单元格,而不是在每次重新加载单元格时都在顶部重新应用它?
此处是视图调试器中的问题图片:
最简单的方法是为单元格或原型单元格创建一个单独的 xib。在那里设计你的单元格,在 cellForItemAtIndexPath 中你只需操纵你的视图并为你的标签、图像和其他控制器设置值。
UICollectionViewCell
被重用。因此,避免在 collectionView:cellForItemAtIndexPath:
中每次都执行 addSubView:
(直接或间接,如您的情况:collectionView:cellForRowAtIndexPath:
正在调用 initData:
,而 addSubView:
正在调用 addSubView:
]。 =27=]
您仅通过代码使用 UICollectionView
和 UICollectionViewCell
。
所以没有 XIB/Storyboard 是单元格,也没有 IBOutlet
.
根据 dequeueReusableCellWithReuseIdentifier:forIndexPath:
的文档,这就是你属于的部分:
If you registered a class for the specified identifier and a new cell
must be created, this method initializes the cell by calling its
initWithFrame:
method.
因此,在 CDCChannelStrip.m 中,覆盖 initWithFrame:
并初始化其属性(即 "always" visible/used)。
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_myImageViewProperty = [[UIImageView alloc] initWithFrame:someFrame];
[self addSubview:_myImageViewProperty];
etc.
}
return self;
}
-(void)updateWithChannel:(NSInteger)channel
{
self.channelNumber = channel;
self.channelLabelName = @"Something";
//etc.
}
您也可以使用 prepareForReuse
到 "reinit" 单元格作为 "virgin"(例如它就在 initWithFrame:
之后。
-(void)prepareForReuse
{
[super prepareForReuse];
self.channelLabelName = @"";
self.backgroundColor = [UIColor clearColor];
//etc.
[self.sometimesThatImageIsShown setHidden:YES];
}
我使用这个函数创建了一个单元格:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
BOOL isFocusOn = [_userDefault boolForKey:@"mixFocusOn"];
CDCChannelStrip *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
if (isFocusOn == TRUE) {
NSNumber *setChan = [self.focusChannels objectAtIndex:indexPath.section];
NSInteger chanInt = [setChan intValue];
[cell initData:(chanInt)];
[self getParameters:(setChan)];
} else {
NSInteger chanInt = indexPath.section;
NSNumber *chanNum = [NSNumber numberWithInt:chanInt]; // doesnt matter
[cell initData:(chanInt)]; // init
[self getParameters:(chanNum)]; // params
}
[self.mixMonitorView setChannelsStripToType:(cell)];
cell.clipsToBounds = YES;
return cell;
}
有问题的函数是 initData
,它看起来像这样:
- (void)initData:(NSInteger)channel {
self.isBus = false;
self.isSendChan = false;
self.recallSafeFade = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"recallSafe"]];
self.recallSafeFade.y = 80;
[self.recallSafeFade setUserInteractionEnabled:YES];
self.recallSafeHead = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"recallSafeHeadamp"]];
[self.recallSafeHead setUserInteractionEnabled:NO];
self.recallSafePan = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"recallSafePan"]];
self.recallSafePan.y = 768 - 141;
[self.recallSafePan setUserInteractionEnabled:YES];
self.channelNumber = channel;
[self setClipsToBounds:NO];
_background = [[UIView alloc] initWithFrame:CGRectMake(0, 80, 122, 547)];
[_background setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"singleFader"]]];
[self addSubview:_background];
[self addChannelName];
[self addInput];
[self addPan];
[self addOn];
[self addMeter];
[self addFader];
}
所以我遇到的问题是,我需要调用此函数来设置我的自定义单元格,以按照我需要的方式查看和运行。但是,每次由于状态更改我在 collectionview 上调用重新加载时,它会将新视图分层放置在旧视图的顶部(由于重复出现 imageview alloc)
那么我如何才能自动将此功能应用于每个单元格,而不是在每次重新加载单元格时都在顶部重新应用它?
此处是视图调试器中的问题图片:
最简单的方法是为单元格或原型单元格创建一个单独的 xib。在那里设计你的单元格,在 cellForItemAtIndexPath 中你只需操纵你的视图并为你的标签、图像和其他控制器设置值。
UICollectionViewCell
被重用。因此,避免在 collectionView:cellForItemAtIndexPath:
中每次都执行 addSubView:
(直接或间接,如您的情况:collectionView:cellForRowAtIndexPath:
正在调用 initData:
,而 addSubView:
正在调用 addSubView:
]。 =27=]
您仅通过代码使用 UICollectionView
和 UICollectionViewCell
。
所以没有 XIB/Storyboard 是单元格,也没有 IBOutlet
.
根据 dequeueReusableCellWithReuseIdentifier:forIndexPath:
的文档,这就是你属于的部分:
If you registered a class for the specified identifier and a new cell must be created, this method initializes the cell by calling its
initWithFrame:
method.
因此,在 CDCChannelStrip.m 中,覆盖 initWithFrame:
并初始化其属性(即 "always" visible/used)。
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_myImageViewProperty = [[UIImageView alloc] initWithFrame:someFrame];
[self addSubview:_myImageViewProperty];
etc.
}
return self;
}
-(void)updateWithChannel:(NSInteger)channel
{
self.channelNumber = channel;
self.channelLabelName = @"Something";
//etc.
}
您也可以使用 prepareForReuse
到 "reinit" 单元格作为 "virgin"(例如它就在 initWithFrame:
之后。
-(void)prepareForReuse
{
[super prepareForReuse];
self.channelLabelName = @"";
self.backgroundColor = [UIColor clearColor];
//etc.
[self.sometimesThatImageIsShown setHidden:YES];
}