Reputation: 31955
I want to append a new object to my Array, which is defined as var
in my Swift app, but despite me defining it as var
, the following error occurred when I tried to append it.
`Immutable value of type 'Any[]' only has mutating members named 'append'`
Here's my code:
var contactsArray: Any[]!
func popoverWillClose(notification: NSNotification) {
if popoverTxtName.stringValue != "" && popoverTxtContactInfo.stringValue != "" {
contactsArray.append(makeDictionaryRecord(popoverTxtName.stringValue, withInfo: popoverTxtContactInfo.stringValue))
}
}
(makeDictionaryRecord(withInfo:)
method takes two String
and returns Dictionary<String, Any>
)
My original code defines contactsArray
as let
, and later I found it was my mistake, so I changed it to var
. However, things still didn't make it so far.
I also changed the type of components of contactsArray
to AnyObject[]
, Any[]
, and AnyObject[]!
, but nothing didn't change at all.
( That being said, since the contactsArray
has to take Dictionary
within it, it has to be defined as either Any[]
or Any[]!
, since Dictionary
is defined as struct, if I understand it correctly. )
What's wrong with my code? How can I properly append the component to contactsArray
?
Upvotes: 17
Views: 11296
Reputation: 93276
Problem 1: You've defined contactsArray
as an implicitly unwrapped Optional, but the values of Optional variables are always immutable. You can define it this way instead to allow appending values:
var contactsArray: [Any]
Update: This hasn't been a problem since Swift introduced assignment through optional chaining. With implicitly unwrapped optionals, this happens automatically.
Problem 2: You haven't given the array an initial value -- the compiler starts complaining about that when you fix problem 1 for an implicitly unwrapped optional, that means the value is nil
, so you'll get a runtime exception. The solution is to initialize the variable with an empty array:
var contactsArray: [Any]! = []
You almost never need an optional Array—an empty array is just as good a signifier of "no values" as nil
, and safer, to boot. If you decide to use an optional array anyway, use a regular optional (i.e., declared with ?
), not an implicitly unwrapped one:
var contactsArray: [Any]? = []
Upvotes: 13
Reputation: 71810
The syntax for array declaration has been changed, it's now
var contractsArray: [Any] = []
Also if you're modifying an array as part of a struct or an enum you might see this error. A struct or an enum is a value type and the method needs the mutating
keyword:
struct contacts {
var contactsArray:[Any] = []
mutating func popoverWillClose(notification: NSNotification) {
if popoverTxtName.stringValue != "" && popoverTxtContactInfo.stringValue != "" {
contactsArray.append(makeDictionaryRecord(popoverTxtName.stringValue, withInfo: popoverTxtContactInfo.stringValue))
}
}
}
In addition you cannot save instances of a struct with mutating methods as a constant using the let
keyword, it needs to be declared as var
because the value for the variable will change when you call a mutating function.
Upvotes: 11