Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/99.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将新初始化的UIImageView传递给类的属性(UIImageView类型)时是否给出nil?_Ios_Swift - Fatal编程技术网

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