DevAndArtist
DevAndArtist

Reputation: 5149

Swift 2.0 beta: are protocols kinda broken in Xcode beta 5?

Currently I'm working on my new App written with Swift 2.0. Today I faced two strange errors in Xcode beta 5. I'd love if someone with a previous beta version of Xcode can confirm if I'm right or not. I also could misunderstand something, so I'll appreciate any feedback.

Here is some example code that made me struggle a while:

// 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

Upvotes: 3

Views: 325

Answers (2)

Kametrixom
Kametrixom

Reputation: 14973

I think the second one isn't a bug as well for the same reason that you can't modify an item in a dictionary directly, or that you can't change elem in for elem in array { ... }.

Something has to be saved to be able to change it. Because you're returning the protocol type, the compiler can't know whether it's a struct or a class, whereas if it's a struct the operation of changing it would have no effect because it's not persisted in any way and structs aren't passed by reference. That's why Thomas' workaround works. Maybe it'll work too if returnInterface returned a class instance, instead of the protocol type.

EDIT: Just tried it out: Indeed it works either if you return SomeClass instead of SomeInterfaceProtocol or if you change the protocol to a class protocol, as it can't be a struct

protocol SomeInterfaceProtocol : class {
    var someBool: Bool { get set }
}

class SomeClass: SomeInterfaceProtocol {
    var someBool: Bool = false

    func returnInterface() -> SomeInterfaceProtocol {
        return self
    }
}

or

protocol SomeInterfaceProtocol {
    var someBool: Bool { get set }
}

class SomeClass: SomeInterfaceProtocol {
    var someBool: Bool = false

    func returnInterface() -> SomeClass {
        return self
    }
}

both work

Upvotes: 2

Thomas Tempelmann
Thomas Tempelmann

Reputation: 12079

The first error can be solved if you add the modifier mutating before the extension func declaration like this:

mutating func someFunction(someString: String) {

I suspect that's a change in the language.

The other one puzzles me as well. At least, here's a work-around:

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

Upvotes: 2

Related Questions