You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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) 
}

实际显示效果:
图片显示效果

问题原因分析

  1. UIImage.size是只读属性:你直接给receivedimg.image?.size赋值的做法是错误的,UIImage的size属性仅用于获取图片原始尺寸,不支持直接修改,这就是报错的核心原因。
  2. 调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:03:26