Swift: Failed to assign value to a property of protocol?
You have to define the protocol as a class
protocol:
protocol ValueProvider : class {
var value: String {get set}
}
Then
var value: String {
get { return v.value }
set { v.value = newValue }
}
compiles and works as expected (i.e. assigns the new value to the
object referenced by v1
if v1 != nil
, and to the object
referenced by v2
otherwise).
v
is a read-only computed property of the type ValueProvider
.
By defining the protocol as a class protocol the compiler knows
that v
is a reference type, and therefore its v.value
property can be modified even if the reference itself is a constant.
Your initial code example works because there the v
property has
the type A
which is a reference type.
And your workaround
set {
var tmp = v1 ?? v2
tmp.value = newValue
}
works because (read-write) properties of variables can be set in
any case (value type or reference type).
Swift protocol settable property through a read-only property
Change your protocol declaration to this:
protocol AProtocol:class {
var name: String { get set }
}
Otherwise, it is taken by default as a value type. Changing a value type's property replaces the value type instance (as shown by the setter observer). And you can't do that if the reference is a let
reference.
Specify a settable property/variable in a protocol
The protocol might be implemented by either classes and structs - that prevents you from changing the internal status of an instance of a class or struct implementing that protocol using an immutable variable.
To fix the problem you have to either declare the food
variable as mutable:
func eat() {
var food = nextItem
food.eaten = true // (!) ERROR: Cannot assign to result of this expression
}
or declare the EdibleThing
protocol to be implementable by classes only:
protocol EdibleThing : class {
var eaten: Bool { get set }
}
Note that this happens because food
is a variable of EdibleThing
type - the compiler doesn't know if the actual instance is a value or reference type, so it raises an error. If you make it a variable of a class type, like this:
let food: Pickle = nextItem as! Pickle
the compiler knows without any ambiguity that it's a reference type, and in that case it allows the assignment. But I guess that breaks your app logic... so consider it just as an example
Cannot assign to generic property in protocol
You can do it like this
//: Playground - noun: a place where people can play
import Cocoa
protocol StringIdentifiable {
var id: String? { get }
}
protocol Foo: class {
associatedtype AnyStringIdentifiable: StringIdentifiable
var entity: AnyStringIdentifiable? { get set }
}
protocol Bar {
//var foo: Foo { get set } // can't do because Foo is generic
associatedtype AnyFoo: Foo
var foo: AnyFoo { get set }
}
extension Bar {
func setEntity(_ entity: AnyFoo.AnyStringIdentifiable) {
foo.entity = entity
}
}
Within Bar you can use AnyFoo.AnyStringIdentifiable
to make sure the types are correct when setting foo.entity
, because foo.entity
is of the type AnyFoo.AnyStringIdentifiable
.
Cannot set value conforming to protocol to property with protocol type
You need to remove the files from your test target since you're already importing your whole project with @testable.
Cannot assign to property in protocol constrained to class - Swift compiler error
In the first case it should be considered an "unimplemented feature" (that the compiler cannot infer the behavior of a class in this context). So to fix it you have to make the value
a var
:
func afterViewInstantiated <V : ViewForViewModel where V: UIViewController, V.ViewModelType: AnyObject>(var view : V, viewModel: V.ViewModelType) -> V
In the second case you should provide more information about the error (message) and the types. Where does V
come from?
Cannot assign to property: 'point' is a 'let' constant
PointType
as a protocol, as written, could apply to either a value type (such as a struct) or a reference type (such as a class). If it were a value type and passed to your function without inout
, it would be immutable.
If your PointType
is always going to be a reference type (and thus always mutable from inside a function where it's pointed to by reference), you can fix your error by saying that it has to be AnyObject
:
protocol PointType : AnyObject {
Related Topics
Xcode Error While Validation - "Your Binary Is Not Optimized for iPhone 5"
How to Completely Hide the Status Bar in iOS Using Cordova
Open Links in Safari Instead of Uiwebview
Add Cocoapods to Tests Target Too
How to Send Email Using Mfmailcomposeviewcontroller in Simulator
How to Do Weak Linking in Swift
Main.Async VS Main.Sync() VS Global().Async in Swift3 Gcd
Find Uialertview Without Having Reference to It iOS 7
Accessing Variables from Another Viewcontroller in Swift
Codesign Returned Unknown Error -1=Ffffffffffffffff
How to Create a Uiimage from the Current Graphics Context
Get Pixel Value from Cvpixelbufferref in Swift
Setting Up Uiscrollview to Swipe Between 3 View Controllers