Xcode13.0 beta3用Swift并发拉取Unsplash图片元数据时报错
问题原因
你看到的奇怪报错是因为:
- 你定义的
UnsplashData、Urls、UnsplashDataLinks、User几个结构体的所有存储属性均为可选类型,且你没有手动声明成员初始化器,Swift自动生成的初始化器要求你为所有属性传入对应实参,你当前仅传入了urls、links、user三个参数,其余参数缺失触发了编译器的错误提示,提示内容是编译器匹配到错误的初始化方法导致的误报,并非真的需要你添加as! Decoder。
解决方案
方案1:补全初始化参数(直接修复当前报错)
你可以在初始化各个结构体实例时,为缺失的可选参数传入nil,sponsorship属性传入JSONNull()实例即可:
catch { print("Failed to fetch image") return UnsplashData( id: nil, createdAt: nil, updatedAt: nil, promotedAt: nil, width: nil, height: nil, color: nil, blurHash: nil, unsplashDataDescription: nil, altDescription: nil, urls: Urls(raw: "", full: nil, regular: nil, small: nil, thumb: nil), links: UnsplashDataLinks(linksSelf: nil, html: "", download: nil, downloadLocation: nil), categories: nil, likes: nil, likedByUser: nil, currentUserCollections: nil, sponsorship: JSONNull(), user: User(id: nil, updatedAt: nil, username: nil, name: "", firstName: nil, lastName: nil, twitterUsername: nil, portfolioURL: nil, bio: nil, location: nil, links: nil, profileImage: nil, instagramUsername: nil, totalCollections: nil, totalLikes: nil, totalPhotos: nil, acceptedTos: nil), exif: nil, location: nil, views: nil, downloads: nil ) }
方案2:给结构体属性添加默认值(简化后续初始化)
你可以在定义结构体的可选属性时直接设置默认值为nil,这样Swift自动生成的初始化器会自动为这些参数添加默认值,你后续初始化时就可以只传需要自定义的参数:
示例修改:
struct UnsplashData: Codable { let id: String? = nil let createdAt, updatedAt, promotedAt: Date? = nil let width, height: Int? = nil // 其余所有可选属性都加上 = nil 的默认值 // ... } // 其余的Urls、UnsplashDataLinks、User等结构体也做同样修改
修改完成后,你原来catch块里的初始化代码就可以正常运行,不需要补全所有参数。
方案3:优化错误处理逻辑(更符合Swift规范)
更推荐的做法是直接将函数改为可抛类型,不需要在函数内部捕获错误返回无效的空实例,将错误抛给上层调用方处理,逻辑更清晰:
func getURL(apiURL: URL) async throws -> UnsplashData { let (data, _) = try await URLSession.shared.data(from: apiURL) return try JSONDecoder().decode(UnsplashData.self, from: data) }
上层调用时再通过do-catch捕获对应错误做自定义处理即可。
内容的提问来源于stack exchange,提问作者Arnav Motwani
相关产品推荐
相关产品推荐

