即使已设置,图像也不会显示在UIImageView中

时间:2019-02-13 16:16:40

标签: ios swift uicollectionview uiimageview uiimage

我有一个带有UIImageView的collectionViewHeader,设置为具有灰色backgroundColor。有一个addPhotoButton,它将用户带到另一个Controller。当他们选择图像时,它会返回到原始控制器,并且应该是UIImageView中的图像。

这是collectionViewHeader中的代码:

var selectedImage: UIImage? {
    didSet {
        self.imageView.image = selectedImage!
        print("This is the selectedImage:", selectedImage!)
    }
}


let imageView: UIImageView = {
    let iv = UIImageView()
    iv.backgroundColor = UIColor.rgb(red: 234, green: 246, blue: 246)
    iv.contentMode = .scaleAspectFill
    iv.clipsToBounds = true
    return iv
}()

这是我遇到的每个教程或StackOverflow帖子都说要做的。和打印语句:

print("This is the selectedImage:", selectedImage!)

正在打印:

This is the selectedImage: <UIImage: 0x600001000380>, {485, 482}

所以图像在那里,但是没有放在UIImageView中。

imageView将被添加到子视图中并锚定以在标题的init中设置大小:

override init(frame: CGRect) {
    super.init(frame: frame)

    addSubview(imageView)
    addSubview(addimageButton)
    addSubview(addimageText)

    if #available(iOS 11.0, *){
        eventImageView.anchor(top: safeAreaLayoutGuide.topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: frame.width, height: 175)
    } else {
        // Fallback on earlier OS?
    }
    addimageButton.anchor(top: eventImageView.topAnchor, left: eventImageView.leftAnchor, bottom: nil, right: imageView.rightAnchor, paddingTop: 25, paddingLeft: (imageView.bounds.size.width - addimageButton.bounds.size.width) / 2, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    addimageText.anchor(top: nil, left: imageView.leftAnchor, bottom: imageView.bottomAnchor, right: imageView.rightAnchor, paddingTop: 0, paddingLeft: (imageView.bounds.size.width - addimageButton.bounds.size.width) / 2, paddingBottom: 25, paddingRight: 0, width: 0, height: 0)
}

selectedImage是在此处另一个控制器的标题中设置的:

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! PhotoSelectorHeader

    self.header = header

    header.photoImageView.image = selectedImage

    if let selectedImage = selectedImage {
        if let index = self.images.index(of: selectedImage) {
            let selectedAsset = self.assets[index]

            let imageManager = PHImageManager.default()
            let targetSize = CGSize(width: 600, height: 600)
            imageManager.requestImage(for: selectedAsset, targetSize: targetSize, contentMode: .default, options: nil, resultHandler: { (image, info) in

                header.photoImageView.image = image

            })

        }
    }

    return header
}

fileprivate func setupNavigationButtons() {
    navigationController?.navigationBar.tintColor = .black
    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(handleCancel))

    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Select", style: .plain, target: self, action: #selector(handleNext))
}

@objc func handleNext() {
    let addPhotoHeader = AddPhotoHeader()
    addPhotoHeader.selectedImage = header?.photoImageView.image
    navigationController?.popViewController(animated: true)
}

我确定这里缺少一个快速步骤,但是我已经被困了几天了!

如果您认为问题可能在我的项目中的其他地方,请告诉我。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

两个问题:

  1. 您不会在主线程上调用此命令(如果从主线程进行设置,则可以起作用,但是我会假设它不是,因为UIImageView是“请适当更新。

  2. (可选的修复程序),您正在通过强制投射可选的selectedImage来请求崩溃。

var selectedImage: UIImage? {
    didSet {
        DispatchQueue.main.async { [weak self] in
            // Don't force-cast (!) the optional selectedImage.
            // Since you can assign a nil image to self?.imageView.image, do that instead
            // Other option is adding a guard-statement here:
            // guard selectedImage != nil else { return }
            self?.imageView.image = selectedImage
            print("This is the selectedImage:", selectedImage)
        }
    }
}

每当设置了与UI相关的内容但未在视觉上进行更新,而其他一切看起来都很好时,很有可能跳转到主线程将起作用。主线程保留用于所有用户界面更改,例如更新图像,刷新表视图或弄乱约束。

几乎所有包含UIUIImageView)的对象都只需要在主线程上进行更新。可能出现的问题范围从UI对象更新的严重延迟到崩溃。

但是,任何长时间运行的任务或繁重的过程(例如网络请求或处理像素级别的图片)应该在主线程上运行,否则您的用户界面将在该过程结束时停止。

@twostraws(Twitter)很好地在这里解释了主线程:https://www.hackingwithswift.com/read/9/4/back-to-the-main-thread-dispatchqueuemain

他提到了这一点,但我完全同意:

  

这一点非常重要,需要重复两次:在后台线程上执行用户界面工作永远都不行。

希望这会有所帮助!