iOS Swift Error: 'T' is not convertible to

2019-04-10 11:47发布

I am attempting to create an extension method for the Array type to allow for removing an item from an array

extension Array {
    func remove(item: AnyObject) {
        for var i = self.count - 1; i >= 0; i-- {
            if self[i] == item {
                self.removeAtIndex(i)
            }
        }
    }
}

On the test condition if self[i] == item, I get the following error: 'T' is not convertible to 'MirrorDisposition'

I've tried many different things, which include:

  • Using generics: remove<T>(item: T)
  • Using the === operator, which just gives the error 'T' does not conform to protocol 'AnyObject'

I'm new to Swift, so this is where my knowledge runs out. Any suggestions would be greatly appreciated.

标签: swift ios8
5条回答
做自己的国王
2楼-- · 2019-04-10 12:17

The way I would write this function is like this:

mutating func remove<U where U : Equatable>(item: U) {
    for var i = self.count - 1; i >= 0; i-- {
        if self[i] as U == item {
            self.removeAtIndex(i)
        }
    }
}

Be sure to decorate your function with mutating.

I would use a different type parameter U since you can't really change Array's type parameter to be Equatable. Then I would try to cast the items to U to do the comparison.

Of course, this will fail if you try to call this function with an Array that is instantiated with a non-equatable type.

查看更多
趁早两清
3楼-- · 2019-04-10 12:18

This is not a solution but if you are trying to remove an item from an array, this is how I do it:

var numbers = [1, 2, 3, 4, 5] if let possibleIndex = find(numbers, 1) { numbers.removeAtIndex(possibleIndex) }

查看更多
欢心
4楼-- · 2019-04-10 12:21

You are getting an error because the compiler can't guarantee that the element stored in your array can be compared with ==. You have to ensure that it the contained type is Equatable. However, there is no way to add a method to a generic class that is more restrictive than the class itself. It is better to implement it as a function:

func removeItem<T: Equatable>(item: T, var fromArray array: [T]) -> [T] {
    for i in reverse(0 ..< array.count) {
        if array[i] == item {
            array.removeAtIndex(i)
        }
    }
    return array
}

Or you could add it as a more generic extension:

extension Array {
    mutating func removeObjectsPassingTest(test: (object: T) -> Bool) {
        for var i : Int = self.count - 1; i >= 0; --i {
            if test(object: self[i]) {
                self.removeAtIndex(i)
            }
        }
    }
}

Then you can do this:

var list: [Int] = [1,2,3,2,1]
list.removeObjectsPassingTest({$0 == 2})
查看更多
迷人小祖宗
5楼-- · 2019-04-10 12:24

The error message is confusing. The problem why it does not work is because Swift compiler can not find == operator for Array's element type T. For this to work T would need to conform to Equatable protocol.

查看更多
Melony?
6楼-- · 2019-04-10 12:28

I don't know what is MirrorDispsition, but I think the problem is that you can't always equate two objects in Array, because they are not guaranteed to be equatable.

Edit: Look at tng's solution. It will only work with equatable items, though.

查看更多
登录 后发表回答