Ios 将新初始化的UIImageView传递给类的属性(UIImageView类型)时是否给出nil?
我有一个Ios 将新初始化的UIImageView传递给类的属性(UIImageView类型)时是否给出nil?,ios,swift,Ios,Swift,我有一个CustomCollectionViewController和一个CustomCollectionViewCell。我将UIImageView拖放到故事板中的CustomCollectionViewCell上,并将其绑定到代码中 然后,我尝试在collectionView(\uu:cellForItemAt:)中使用以下行初始化单元格: customCell.imageView=UIImageView(图像:图像[indexath.item]) 当collectionView(u0;:c
CustomCollectionViewController
和一个CustomCollectionViewCell
。我将UIImageView
拖放到故事板中的CustomCollectionViewCell
上,并将其绑定到代码中
然后,我尝试在collectionView(\uu:cellForItemAt:)
中使用以下行初始化单元格:
customCell.imageView=UIImageView(图像:图像[indexath.item])
当collectionView(u0;:cellForItemAt:)
返回时,customCell.imageView
为nil
。但是对于imageCell.imageView.image=images[indexath.item]
,它是有效的
为什么会这样?谢谢
代码段: 内部
类CustomCollectionViewController
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath)
if let imageCell = cell as? ImageCollectionViewCell, images[indexPath.item] != nil {
imageCell.imageView = UIImageView(image: images[indexPath.item]) // doesn't work, cell.imageView would be nil
imageCell.imageView.image = images[indexPath.item] // work
}
return cell
}
以及:
由于imageView被声明为弱
@IBOutlet weak var imageView: UIImageView!
为其分配一个新实例将使其nil
,因为lhs无法保留rhs,请查看警告
如果希望它工作,请删除弱
,因为默认值为强
@IBOutle var imageView: UIImageView!
但这对您当前的情况毫无意义,因此只需指定图像即可。设置imageView属性是个坏主意。这是一个插座,由故事板/xib实例化。我猜您创建的新UIImageView不会被保留,因为imageView被声明为弱
如果首先使用Interface builder添加任何视图或控件,则应避免“重新创建”此类视图或控件。详细回答: 让我们将旧的ImageView(故事板中的一个)命名为A,将新的ImageView(在代码处创建)命名为B
UIImageView(image:images[indexPath.item])
该变量将仅被称为引用
您已将引用设置为弱引用,这意味着一旦它丢失任何强引用(如在视图层次结构中),它就会被销毁。当您将其指定为B时,B没有指定到其他任何位置,因此它立即被销毁,因此您的引用变为零。只要将A从层次结构中删除,它仍然位于单元格上(在子视图数组中,数组往往包含强引用)。您必须理解链接引用(弱或强)和作为视图中的子视图(强)之间的区别。在对代码进行任何更改之前,imageView有两个链接—代码中的弱指针和单元格层次结构中的强指针。当您用B替换引用时,A将丢失弱引用,但在单元格中仍有强引用。B只有微弱的辐射,所以在实际使用之前,它被立即销毁
你的逻辑也有问题。仅仅因为您更改了对B imageView的引用,并不意味着图像将出现在您的单元格中。您的B需要设置其框架或约束,并添加到某些视图层次(单元)中。实际上,您需要的只是将A.image属性更改为新图像,即imageCell.imageView.image=images[indexPath.item]
请阅读更多关于内存管理和弱、强引用的信息
简短回答:
删除此行
imageCell.imageView=UIImageView(图像:图像[indexath.item])
所以你的代码看起来像
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath)
if let imageCell = cell as? ImageCollectionViewCell,
let image = images[indexPath.item]
{
imageCell.imageView.image = image
}
return cell
}
与前面提到的其他答案一样,问题在于
imageCell.imageView
很弱,因此它只引用在另一个地方保留很强的imageView
imageCell.imageView最初引用的是您在故事板中拖放的imageView。当一个视图包含在另一个视图中时,它将被强烈保留
如果要替换该ImageView,则需要创建对新ImageView的强引用,例如,将其添加到另一个视图中,如下所示:
let newImageView = UIImageView(image: images[indexPath.item])
imageCell.contentView.addSubview(newImageView)
imageCell.imageView = newImageView
但正如其他人之前所提到的,最好只替换当前ImageView的UIImage。问题不仅在于引用,还在于包含强引用的视图层次结构您指的是什么??如果cell xib/protypecell/programmetically cell不会阻止imageView的释放旧的imageView(通过故事板设置)保持为强,因为它仍然在cell的子数组中(数组保持强引用),因此即使将此变量更改为强,旧的imageView仍然存在-它没有自动消失-您只是失去了对它的直接引用…我没有说它会消失,删除弱项将使imageView变量为非零,或者只是创建为局部变量,将其作为子视图添加到单元格中,然后更改变量。这样,弱引用将是非nilfix imageCell.contentView.addSubview(newImageView)的关键:您必须理解链接引用(弱或强)和作为视图中的子视图(强)之间的区别。非常感谢您的深入回答!
let newImageView = UIImageView(image: images[indexPath.item])
imageCell.contentView.addSubview(newImageView)
imageCell.imageView = newImageView