2

I have this enum:

enum Animal {       
    case cat(CatModel)
    case dog(DogModel)
}

And an array of animals:

var animals: [Animal]

I need to find a Cat object in this array by a property that Dog doesn't have. litterBoxId for example.

let cat = animals.first(where: {$0.litterBoxId == 7})

This of course has an error:

Value of type 'MyViewController.Animal' has no member 'litterBoxId'

How can I accomplish this? I also tried

($0 as CatModel).litterBoxId
4

2 回答 2

2

You can use pattern matching to accomplish this with 2 ways.

Using switch:

let cat = animals.first(where: {
    switch $0 {
    case .cat(let catModel) where catModel.litterBoxId == 7:
        return true
    default:
        return false
    }
})

or if:

let cat = animals.first(where: {
    if case .cat(let catModel) = $0, catModel.litterBoxId == 7 {
        return true
    }
    return false
})

Update: As @Alexander-ReinstateMonica mentioned in his commnet, it would be more appropriate to hide this logic behind a function like this:

extension Animal {
    func matches(litterboxID: Int) -> Bool {
        switch self {
        case .cat(let catModel) where catModel.litterBoxId == 7:
            return true
        default:
            return false
        }
    }
}

and then your code will be much cleaner:

let cat = animals.first(where: { $0.matches(litterboxID: 7) })
于 2020-08-20T22:54:06.687 回答
1

This probably isn't a good use of enums, but here is how it could work:

struct CatModel {
    let litterBoxID: Int
}

struct DogModel {
    let litterBoxID: Int
}

enum Animal {       
    case cat(CatModel)
    case dog(DogModel)
    
    var litterBoxId: Int {
        switch self {
        case .cat(let cat): return cat.litterBoxID
        case .dog(let dog): return dog.litterBoxID
        }
    }
}

var animals: [Animal] = []
let cat = animals.first(where: { $0.litterBoxId == 7 })

You would be much better off using a protocol:

struct CatModel: Animal {
    let litterBoxID: Int
}

struct DogModel: Animal {
    let litterBoxID: Int
}

protocol Animal {
    var litterBoxID: Int { get }
}

var animals: [Animal] = []
let cat = animals.first(where: { $0.litterBoxID == 7 })
于 2020-08-20T22:45:18.640 回答