【问题标题】:Swift 2.0 beta: are protocols kinda broken in Xcode beta 5?Swift 2.0 beta:Xcode beta 5 中的协议有点坏了吗?
【发布时间】:2015-08-16 19:53:39
【问题描述】:

目前我正在开发使用 Swift 2.0 编写的新应用程序。今天我在Xcode beta 5 中遇到了两个奇怪的错误。如果有以前测试版 Xcode 的人可以确认我是否正确,我会很高兴。我也可能会误解一些东西,所以我会很感激任何反馈。

以下是一些让我苦苦挣扎的示例代码:

// Frist bug
protocol SomeProtocol {

    var someArray: [String] { get set } // #1 bug
}

extension SomeProtocol {

    func someFunction(someString: String) {

        self.someArray.append(someString) // #1: Immutable value of type '[String]' only has mutating members named 'append'
    }
}

// Second bug
protocol SomeInterfaceProtocol {

    var someBool: Bool { get set } // #2 bug
}

class SomeClass: SomeInterfaceProtocol {

    var someBool: Bool = false

    func returnInterface() -> SomeInterfaceProtocol {

        return self
    }
}

let someInstance = SomeClass()

// can't set the value
someInstance.returnInterface().someBool = true // #2: Cannot assign to property: function call returns immutable value

【问题讨论】:

    标签: xcode protocols swift2


    【解决方案1】:

    如果在扩展func声明之前添加修饰符mutating可以解决第一个错误,如下所示:

    mutating func someFunction(someString: String) {
    

    我怀疑这是语言的变化。

    另一个也让我困惑。至少,这是一个解决方法:

    var c = someInstance.returnInterface()
    c.someBool = true
    

    【讨论】:

    • 用这个解决了第一个,我完全忘记了我的协议也可以是结构类型。解决第一个问题的另一种方法是说它应该只用于类的协议protocol SomeProtocol: class { /*...*/ },它就可以工作。我对那个不好。 :D 第二种解决方法有效,但我认为这是测试版的真正错误。
    • 是的,我也认为这是一个错误。帮我们大家一个忙,去 bugreporting.apple.com 写下来。
    • 我会的,我应该选择哪种产品?我以Sample Code 的身份在 Xcode 7 beta 上发布了 3 个其他 Swift 2.0 错误 3 次,但还没有发生任何事情。
    • 我将它们发布为“开发者工具”问题。此外,如果您发布有趣的问题,也可以将它们发布到 openradar.appspot.com - 是的,Apple 修复它们可能需要一些时间,如果有的话 :)
    • 我认为第二个也不是错误,因为您不能直接修改字典中的项目,或者您不能更改 @987654328 中的 elem @。必须保存一些东西才能改变它。因为您要返回协议类型,所以编译器无法知道它是结构还是类,而如果它是结构,则更改它的操作将无效,因为它不会以任何方式持久化。这就是 Thomas 的解决方法有效的原因。如果returnInterface 返回一个类实例而不是协议类型,也许它也会起作用。
    【解决方案2】:

    我认为第二个也不是错误,原因与您无法直接修改字典中的项目或无法更改 for elem in array { ... } 中的 elem 相同。

    必须保存某些内容才能对其进行更改。因为您要返回协议类型,所以编译器无法知道它是结构还是类,而如果它是结构,则更改它的操作将无效,因为它不会以任何方式持久化并且不会传递结构引用。这就是 Thomas 的解决方法有效的原因。如果 returnInterface 返回一个类实例而不是协议类型,也许它也会起作用。

    编辑:刚刚尝试过:确实,如果您返回 SomeClass 而不是 SomeInterfaceProtocol,或者如果您将协议更改为类协议,因为它不能是结构,它确实有效

    protocol SomeInterfaceProtocol : class {
        var someBool: Bool { get set }
    }
    
    class SomeClass: SomeInterfaceProtocol {
        var someBool: Bool = false
    
        func returnInterface() -> SomeInterfaceProtocol {
            return self
        }
    }
    

    protocol SomeInterfaceProtocol {
        var someBool: Bool { get set }
    }
    
    class SomeClass: SomeInterfaceProtocol {
        var someBool: Bool = false
    
        func returnInterface() -> SomeClass {
            return self
        }
    }
    

    两者都有效

    【讨论】:

    • 天哪,我犯了同样的错误两次。第一个解决了我的问题。所以这根本不是一个错误。这是我的愚蠢。谢谢。
    • 好吧,我仍然无法理解为什么returnInterface() 的直接结果导致编译器的反应与通过辅助变量不同。这在我的书中不合逻辑。
    • @ThomasTempelmann 考虑以下引发错误的示例:func get() -> Int { return 1 }; get()++ ++ 应该改变什么?函数中的1?如果您将其更改为 var x = get(); x++ 它可以工作。一般规则是:您不能使用没有var 关键字的更改操作。一个比上面更简单的例子是1++(也会引发错误)
    • 出于好奇,returnInterface() 函数的目的是什么?它似乎充其量是多余的,并且在最坏的情况下为编译器增加了不必要的限制。实例化 SomeClass 的实例并在该实例上设置 someBool 工作正常,那么为什么要中间人呢?
    • 修复第二个错误的另一种方法是告诉编译器该协议仅适用于类protocol SomeInterfaceProtocol: class {... 这样它就知道returnInterface() 返回一个引用类型并且调用变异方法是安全的.
    猜你喜欢
    • 2014-10-15
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多