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

问题描述 投票:0回答:1

我有一个带有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)
}

我确信这里有一个快速的步骤,但我已经被困了几天了!

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

在此先感谢您的帮助!!

ios swift uicollectionview uiimageview uiimage
1个回答
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相关的东西被设置但没有视觉上更新,并且其他一切似乎都很好时,跳转到主线程的机会很有可能。主线程保留用于所有用户界面更改,例如更新图像,刷新表视图或弄乱约束。

几乎任何有UI的对象(UIImageView)都只需要在主线程上更新。可能出现的问题可能包括UI对象更新的主要延迟到崩溃。

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

@twostraws(Twitter)在这里解释主线程非常出色:https://www.hackingwithswift.com/read/9/4/back-to-the-main-thread-dispatchqueuemain

他提到这一点,我不能同意:

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

希望这可以帮助!

© www.soinside.com 2019 - 2024. All rights reserved.