user3476114
user3476114

Reputation: 634

Cannot convert value of type NSNumber to expected argument type NSNumber

I am getting the error in the title when trying to use the argument of a generic function inherited from a base class

Base class:

BaseBottomBar: UIView {
    ...
    func formatDetailText<T>(value: T...) {
        assertionFailure("You shouldn't be using this base class")
    }
}

Child class:

NewTicketBottomBar: BaseBottomBar {

    override func formatDetailText<NSNumber>(value: NSNumber...) {
        let priceAsCurrencyString = NumberFormatter.currencyFormatter.string(from: value[1]) //Error on this line
        assert(priceAsCurrencyString != nil, "The price cannot be nil")
        let newTicketText = String(format: "%4.0f", value[0]) + " / TOTAL : " + priceAsCurrencyString!
        detailLabel.text = newTicketText
    }
}

Cannot convert value of type NSNumber to expected argument type NSNumber

I guess I have my base method prototype wrong in some way but I can't see how.

I wasn't using a generic method in the beginning and the prototype was the following:

func formatDetailText(value: Double...) {
    ...
    let priceAsCurrencyString = NumberFormatter.currencyFormatter.string(from: NSNumber(value: value[1]))
    ...
}

And this was working fine

Any help would be appreciated

Upvotes: 1

Views: 2365

Answers (2)

matt
matt

Reputation: 534950

You seem to think that

override func formatDetailText<NSNumber>(value: NSNumber...) {

resolves the generic <T> in the overridden method as NSNumber. It doesn't. It merely introduces a different name for the generic; NSNumber here is not the NSNumber class, it's just another generic placeholder name, exactly like T (in fact, it is T by another name).

So naturally, when you try to use this placeholder where an NSNumber is expected in NumberFormatter's string(from:), the compiler turns around and says, "Dude [the compiler is from California, this is how it talks], I have no reason to think that your placeholder called "NSNumber" is in fact NSNumber."

You need to give it a reason to think that. What you probably mean is

override func formatDetailText<T>(value: T...) where T : NSNumber {

Upvotes: 3

Craig Siemens
Craig Siemens

Reputation: 13266

The problem is that your code isn't saying that the parameter must be an NSNumber. It's saying that it takes a generic type that you want to call NSNumber, just like you're using T above.

The error message is because there is no guarantee to the compiler that the generic type called NSNumber is a real NSNumber instance. You could pass a string to it for all it knows.

Your override should look like this

override func formatDetailText<T: NSNumber>(value: T...)

Upvotes: 2

Related Questions