Error: Argument type double/string etc. does not conform to expected type “AnyObject”

I watched some iOS programming tutorial and have a question on “AnyObject”.
The bridging does not work.
I have the following code:

import Foundation

class CalculatorBrain
{
    private var accumulator = 0.0
    var internalProgram = [AnyObject]()

    func setOperand (operand: Double) {
        accumulator = operand
        internalProgram.append(operand)
    }
    // ...
}

Same for string…

  • iOS UINavigationBar button remains faded after segue back
  • Swift: Extracting / downcasting CFType based CoreText types in a CFArray
  • Delay next action in SKAction.sequence after runBlock occurs (Swift)?
  • Is it possible to access a shadowed top level function in Swift?
  • Cannot load underlying module for 'RealmSwift'
  • Simplest way to implement a “Read More” button to expand a UITextView in iOS Swift 2?
  • func performOperation (symbol: String) {
        internalProgram.append(symbol)
    } 
    

    I know about NSString and the reference type vs. struct thing, and that double and string are no reference types.
    But anyway in the tutorial the bridging worked fine…
    What could be the reason for my failure?

    3 Solutions Collect From Internet About “Error: Argument type double/string etc. does not conform to expected type “AnyObject””

    As you correctly say, Double and String are not reference types in Swift – they are structs. Therefore you cannot directly store them in an [AnyObject], you would first need to bridge them to Objective-C in order to do so.

    Although bridging to Objective-C in this case is unnecessary – if you want an array of heterogenous types, including value types, then you can use an [Any]:

    var internalProgram = [Any]()
    

    However, from what I can tell, you don’t want a array of anything (it’s very rarely a good idea) – you just want an array that can contain a Double or a String.

    You can describe this with an enum:

    enum OperationArgument { // feel free to give me a better name
        case operand(Double)
        case symbol(String)
    }
    

    And now you can define an array of it:

    var internalProgram = [OperationArgument]()
    
    func setOperand (operand: Double) {
        internalProgram.append(.operand(operand))
    }
    
    func performOperation (symbol: String) {
        internalProgram.append(.symbol(symbol))
    }
    

    Now instead of conditional type-casting to get back the type of each element, you can just use a switch or an if case:

    for element in internalProgram {
        switch element {
        case let .operand(operand):
            print(operand)
        case let .symbol(symbol):
            print(symbol)
        }
    
        if case let .operand(operand) = element {
            print(operand)
        }
    }
    

    To use a Swift value type as an AnyObject, in Swift 3 you need to explicitly cast it to the old Objective-C object type.

    So this

    internalProgram.append(operand)
    

    becomes this

    internalProgram.append(operand as NSNumber)
    

    And this

    internalProgram.append(symbol)
    

    becomes this

    internalProgram.append(symbol as NSString)
    

    The tutorial you are talking about has probably been written with Swift 2 where you just needed to import Foundation.

    var internalProgram = [AnyObject]()
    
    func setOperand (operand: Double) {
        // you have cast operand as AnyObject !!
        internalProgram.append(operand as AnyObject)
    }
    
    setOperand(operand: 10)
    print(internalProgram, type(of: internalProgram)) // [10] Array<AnyObject>