Xcode 9.3(Swift 4.1)中的 Codable '没有初始化器'
Posted
技术标签:
【中文标题】Xcode 9.3(Swift 4.1)中的 Codable \'没有初始化器\'【英文标题】:Codable 'has no initializers' in Xcode 9.3 (Swift 4.1)Xcode 9.3(Swift 4.1)中的 Codable '没有初始化器' 【发布时间】:2018-09-09 23:24:14 【问题描述】:更新到Xcode 9.3(使用Swift 4.1)后,发现如下问题:
创建一个空项目,向其中添加一个新的 .swift 文件并创建两个新类:
class CodableOne: Codable
let some: String
class CodableTwo: Codable
var some: String
构建成功
向CodableOne
添加一个CodableTwo
类型的新常量:
class CodableOne: Codable
let some: String
let another: CodableTwo
class CodableTwo: Codable
var some: String
构建成功
现在将类 CodableTwo
移动到另一个文件(例如 ViewController.swift)
构建失败。
现在有一个错误,它不会消失。 Codable
类不需要初始化器(如前面的步骤所示)。
任何关于这背后的问题以及如何解决的想法将不胜感激!
附: Xcode 9.2 中不存在问题。清理项目/构建路径,重新安装 Xcode 9.3 也无济于事。
【问题讨论】:
不错的发现——提交了一个错误:bugs.swift.org/browse/SR-7315 @Hamish - 这对我来说似乎为时过早。开启“全模块”编译。 @Rob 这对我来说并没有什么不同(编辑:哦,看起来这取决于“编译源”中文件的顺序)。尽管无论如何它不应该有所作为——编译器不应该在整个模块编译下给你不同的行为(它的目的是允许更积极的优化)。 我和@Hamish 在一起;看起来像一个编译器错误。感谢您打开它。 @Andrew 是的,重新排序确实有助于Whole Module
编译,这在错误报告中有所提及。请在 bugs.swift.org/browse/SR-7315 上为该问题投票
【参考方案1】:
作为mentioned in the comments,我必须做两件事:
在Project settings/Build Settings中将Compilation Mode更改为Whole Module:
重新排序项目设置/构建阶段/编译源下的文件。具体来说,我将有错误的文件放在列表的前面。
Protip:如果您搜索文件名并且有多个结果,将文件拖到较小列表中的顶部仍会将其置于最前面。
【讨论】:
该文章中的步骤在 Xcode 9.3 中已过时,该选项已被移动并重命名。它现在在名为“整个模块”的“编译模式”下。也不会给你赏金,因为你的答案实际上是我所说的在赏金标题中不起作用的确切步骤:P @OscarApeland 谢谢你提供的信息,我编辑了它。当我写这个答案时,我不知道你的赏金,我试图组织我发现有效的解决方案。此外,cmets 中也没有提到将有错误的文件放在前面。我完全反对抄袭和复制粘贴 cmets 的答案,我总是添加一些额外的信息(如果没有,我将我的答案标记为社区 wiki)。 不用担心,很好的答案,它显然对某些人有用:) JIRA 错误刚刚被分配给 Apple 的某个家伙,所以希望我们能很快得到一些真正的答案。 不幸的是,当我想在 Objective C 中创建 Swift 对象时,这不起作用。我尝试将 Swift 文件重新排序到顶部,然后将 ObjC 类重新排序到顶部,但这些都不起作用。【参考方案2】:这是Swift 4.1
编译器中的一个错误。要解决此问题,请执行 the4kman 的答案中概述的步骤,或者只需在声明中将 let
更改为 var
,如下所示:
class C1 : Decodable
let str: String
// error: Class 'C1' has no initializers - if class C's `c1` is a let constant.
class C : Decodable
var c1: C1 // << Change to `var`, compilation succeeds.
解决方法courtesy of Apples Swift engineers。
如果这个和 4kmans 的答案都没有帮助,您可以将另一个 init
添加到不会编译的模型中。如果您的类有大量变量,只需使init
崩溃以使编译器满意。 Codable
初始化器仍将被合成。
class C1: Decodable
let str: String
@available(*, deprecated, message: "Do not use.")
private init()
fatalError("Swift 4.1")
【讨论】:
谢谢,这成功了。有趣的是,我的一些 Codable 类已通过上面建议的项目设置更改修复,而其他类也需要此修复。 是的,似乎两者都需要。希望他们能尽快解决这个问题 它有效。如果将 init 标记为private
,则不必担心可用性
@manueGE 这更聪明。我忘记了初始化程序有访问控制。更新了答案。【参考方案3】:
即使我的所有类都在同一个文件中,我也遇到了这个问题,但使用结构更深的类似乎可以工作
【讨论】:
那是因为结构会自动合成另一个init【参考方案4】:试着给你的变量一个这样的初始值(把你的代码改成这个)
class CodableOne: Codable
var some = ""
class CodableTwo: Codable
var some = ""
【讨论】:
不,你不能这样做。这将覆盖解码后的值。以上是关于Xcode 9.3(Swift 4.1)中的 Codable '没有初始化器'的主要内容,如果未能解决你的问题,请参考以下文章
如何在 swift 4.1 和 xcode 9.3 中使用 JSONDecoder 解码嵌套的 JSON 数组和对象?
堆栈视图中的自动约束冲突、Swift 2、iOS 9.3、XCode 7