Swift中使用Kingfisher修改ImageView着色异常问题求助
问题:横向CollectionView选中Cell时图片着色异常(背景覆盖)
我实现了一个横向CollectionView,选中特定Cell时需要修改ImageView的颜色。目前部分图片着色成功,但部分图片出现异常——着色效果表现为背景色直接覆盖整个图片区域,而非仅对图片内容着色。
原实现代码
图片着色函数
func imageWithColor(color1: UIColor) -> UIImage { UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) color1.setFill() let context = UIGraphicsGetCurrentContext()! as CGContext context.translateBy(x: 0, y: self.size.height) context.scaleBy(x: 1.0, y: -1.0); context.setBlendMode(CGBlendMode.normal) let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect context.clip(to: rect, mask: self.cgImage!) context.fill(rect) let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage UIGraphicsEndImageContext() return newImage }
Kingfisher图片加载代码
imageProduct.kf.setImage(with: URL(string:"imageurl"), placeholder: nil) { result in self.imageProduct.image = self.categoryImg.image?.imageWithColor(color1: UIColor.green) }
问题原因
- 混合模式错误:原函数使用
CGBlendMode.normal混合模式,会让填充色直接覆盖整个画布,没有利用图片的Alpha通道限制着色范围,导致透明区域也被填充。 - Kingfisher逻辑错误:没有正确使用加载完成的网络图片,反而引用了
categoryImg的图片,逻辑混乱且无法保证操作的是目标图片。
解决方案
修正后的图片着色函数
extension UIImage { func imageWithTintColor(_ color: UIColor) -> UIImage { UIGraphicsBeginImageContextWithOptions(size, false, scale) defer { UIGraphicsEndImageContext() } color.setFill() // 使用sourceIn混合模式,仅对图片非透明区域填充颜色 draw(in: CGRect(origin: .zero, size: size), blendMode: .sourceIn, alpha: 1.0) return UIGraphicsGetImageFromCurrentImageContext() ?? self } }
这个实现简化了绘图逻辑,通过sourceIn混合模式自动保留图片的Alpha通道,确保着色仅作用于图片内容区域。
修正后的Kingfisher加载代码
imageProduct.kf.setImage(with: URL(string: "imageurl"), placeholder: nil) { [weak self] result in guard let self = self, case .success(let retrievedImage) = result else { return } // 对加载成功的网络图片直接着色 let tintedImage = retrievedImage.imageWithTintColor(.green) self.imageProduct.image = tintedImage }
- 用
weak self避免循环引用 - 从Kingfisher的回调结果中正确获取加载完成的图片
- 直接对目标图片进行着色,确保逻辑正确
内容的提问来源于stack exchange,提问作者Eslam Abotaleb
相关产品推荐
相关产品推荐

