将新初始化的UIImageView传递到类的属性(类型UIImageView)会给出nil吗?

时间:2018-10-16 15:09:05

标签: ios swift

我有一个CustomCollectionViewController和一个CustomCollectionViewCell。我将一个UIImageView拖放到情节提要中的CustomCollectionViewCell上,并将其绑定到代码中。

然后,我尝试使用此行初始化collectionView(_:cellForItemAt:)中的单元格:

customCell.imageView = UIImageView(image: images[indexPath.item])

它不起作用,customCell.imageView返回时nilcollectionView(_:cellForItemAt:)。但是有了imageCell.imageView.image = images[indexPath.item],它就可以了。

为什么会这样?谢谢。


代码段:

class 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
}

并且:

class CustomCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var imageView: UIImageView!
}

4 个答案:

答案 0 :(得分:1)

长答案:

让您将旧ImageView(情节提要中的一个)命名为A,将新ImageView(在代码中创建)命名为B UIImageView(image: images[indexPath.item]) 该变量将被称为引用

您已将参考设置为弱参考,这意味着,一旦失去任何强参考(例如处于视图层次结构中),它就会被销毁。当您将其分配为B时,该B未分配给其他任何地方,因此它立即被销毁,因此您的引用变为nil。只要您将其从层次结构中删除,您的A仍在单元格中(在子视图数组中,并且数组倾向于保留强引用)。您必须了解链接引用(弱或强)与作为视图的子视图(强)之间的区别。在对代码进行任何更改之前,imageView有两个链接-代码中的弱指针和单元层次结构中的强指针。当您用B替换参照时,A失去了弱点,但在单元格本身中仍然具有强参照。 B只是很弱,所以在实际使用之前就被立即摧毁了

您的逻辑也有问题。仅仅因为您更改对B imageView的引用,并不意味着该图像将出现在您的单元格中。您的B需要设置为框架或约束,并添加到某些视图层次结构(单元格)中。您实际需要的只是将A.image属性更改为新图像,就是imageCell.imageView.image = images[indexPath.item]

请阅读有关内存管理和弱而有力的参考文献的更多信息

简短答案:

删除此行

imageCell.imageView = UIImageView(image: images[indexPath.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
}

答案 1 :(得分:0)

由于imageView被声明为weak

@IBOutlet weak var imageView: UIImageView!

为其分配新实例使其nil,因为lhs无法保留rhs,请注意警告

enter image description here

如果您希望它正常工作,请删除weak,因为默认值为strong

@IBOutle var imageView: UIImageView!

但是对于您当前的情况没有任何意义,因此只需分配图片

答案 2 :(得分:0)

设置imageView属性是一个坏主意。这是一个通过情节提要/ xib实例化的出口。我猜测您创建的新UIImageView不会保留,因为imageView被声明为弱。

如果首先使用“界面”构建器添加视图或控件,则应避免“重新创建”此类视图或控件。

答案 3 :(得分:0)

就像已经提到的其他答案一样,问题是imageCell.imageView较弱,因此它仅引用牢固保留在另一个位置的ImageView。

imageCell.imageView最初引用您拖放到情节提要中的ImageView。当一个视图包含在另一个视图中时,它将被强烈保留。

如果要替换该ImageView,则需要创建对新ImageView的强引用,例如,将其添加到另一个View中,如下所示:

let newImageView = UIImageView(image: images[indexPath.item])
imageCell.contentView.addSubview(newImageView)
imageCell.imageView = newImageView

但是正如其他人之前提到的,最好只替换当前ImageView的UIImage。