Swift报错Cannot assign to property: 'size'是只读属性,图片缩放失败求助
iOS图片缩放问题:Cannot assign to property: 'size' is a get-only property
你好!我来帮你梳理下这个问题:你尝试从URL加载图片后发现显示过大,调整receivedimg的frame没效果,接着试图修改图片的size属性时触发了报错——Cannot assign to property: 'size' is a get-only property,你的代码如下:
if let ImageUrl = message.imageUrlLink { receivedimg.frame.size = CGSize(width: 150, height: 150) receivedimg.image?.size = CGSize(width: 150, height: 150) // 报错行 self.receivedimg.loadImageUsingCacheWithUrlString(ImageUrl) }
实际显示效果:
问题原因分析
UIImage.size是只读属性:你直接给receivedimg.image?.size赋值的做法是错误的,UIImage的size属性仅用于获取图片原始尺寸,不支持直接修改,这就是报错的核心原因。- 调整frame无效的可能原因:
- 你的
receivedimg可能使用了Auto Layout约束,直接修改frame会被系统的约束规则覆盖,导致尺寸设置不生效; - 没有正确设置
UIImageView的contentMode,默认的.scaleToFill会让图片拉伸填满整个视图,即使你改了frame,图片也会自动适配视图尺寸,看起来还是“过大”。
- 你的
正确的解决方法
方法1:通过UIImageView的属性实现缩放(推荐)
这是最简单高效的方式,不需要修改图片本身,只要调整视图的尺寸和内容模式即可:
if let imageUrl = message.imageUrlLink { // 1. 正确设置frame(如果不用Auto Layout) receivedimg.frame = CGRect(x: receivedimg.frame.origin.x, y: receivedimg.frame.origin.y, width: 150, height: 150) // 2. 设置合适的contentMode,让图片适配视图 // .scaleAspectFit:保持图片比例,完整显示在视图内 receivedimg.contentMode = .scaleAspectFit // 如果需要让图片填充整个视图(可能裁剪边缘),用下面的配置: // receivedimg.contentMode = .scaleAspectFill // receivedimg.clipsToBounds = true self.receivedimg.loadImageUsingCacheWithUrlString(imageUrl) }
方法2:如果必须修改图片本身的尺寸(比如优化内存)
如果你需要预先缩放图片(比如缓存缩小后的版本),可以通过绘制新图片的方式实现,而不是修改原图片的size:
// 先定义一个图片缩放的工具方法 func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage { let originalSize = image.size // 计算缩放比例,保持图片原有宽高比 let widthRatio = targetSize.width / originalSize.width let heightRatio = targetSize.height / originalSize.height let scaleRatio = min(widthRatio, heightRatio) let newSize = CGSize(width: originalSize.width * scaleRatio, height: originalSize.height * scaleRatio) // 绘制新的图片 UIGraphicsBeginImageContextWithOptions(newSize, false, UIScreen.main.scale) image.draw(in: CGRect(origin: .zero, size: newSize)) let resizedImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return resizedImage ?? image }
然后在图片加载完成后调用这个方法(假设你的加载方法有完成回调):
if let imageUrl = message.imageUrlLink { self.receivedimg.loadImageUsingCacheWithUrlString(imageUrl) { [weak self] loadedImage in guard let self = self, let loadedImage = loadedImage else { return } // 缩放图片到目标尺寸 let resizedImage = self.resizeImage(image: loadedImage, targetSize: CGSize(width: 150, height: 150)) self.receivedimg.image = resizedImage // 同时设置视图的frame或约束,确保容器尺寸正确 self.receivedimg.frame = CGRect(x: self.receivedimg.frame.origin.x, y: self.receivedimg.frame.origin.y, width: 150, height: 150) } }
方法3:如果使用Auto Layout约束
如果你的receivedimg是用约束布局的,直接修改frame会被约束覆盖,应该调整约束的constant值:
// 假设你已经给UIImageView关联了宽度和高度约束的IBOutlet if let imageUrl = message.imageUrlLink { receivedimgWidthConstraint.constant = 150 receivedimgHeightConstraint.constant = 150 // 更新布局 self.view.layoutIfNeeded() receivedimg.contentMode = .scaleAspectFit self.receivedimg.loadImageUsingCacheWithUrlString(imageUrl) }
总结
你的缩放方式确实有误:一是错误地尝试修改UIImage的只读size属性,二是没有正确处理UIImageView的布局和内容模式。优先使用方法1来实现图片缩放,这是iOS开发中最常用的做法,既简单又能保证图片显示效果。
内容的提问来源于stack exchange,提问作者William Loke
相关产品推荐
相关产品推荐

