Протокол приведения к классу в Swift - PullRequest
1 голос
/ 02 октября 2019

Когда мы делаем необязательную цепочку, такую ​​как

var myVar: Int?

if let unwrapped = myVar {

}

Компилятор обрабатывает unwrapped как Int

У меня есть массив классов, которые соответствуют определенному протоколу. Рассмотрим пример:

import Foundation

protocol SomeProtocol: class {}

class A {}
extension A: SomeProtocol {}
class B {}
extension B: SomeProtocol {}
class C {}
extension C: SomeProtocol {}

let arr: [SomeProtocol] = [A(), B(), C()]

arr.forEach{ object in
  if object is A {
    // object is treated like SomeProtocol, not like A class
  }
}

Я могу сделать (object as! A), но это выглядит ужасно. Как мне найти способ для умного преобразования элемента протокола в переменную моего класса?

Ответы [ 3 ]

3 голосов
/ 02 октября 2019

Вы находитесь на правильном пути с необязательной привязкой.

as? - это вариант as!, который оценивается как необязательный тип, к которому вы применяете. Вы можете использовать это в сочетании с необязательной привязкой:

arr.forEach{ object in
  if let a = object as? A { // (object as? A) is of type "A?", but we are unwrapping it
    // a is of type A now
  }
}
2 голосов
/ 02 октября 2019

Использование Сопоставление с образцом в операторе switch

Если вы собираетесь обрабатывать несколько типов в одном цикле, используйте switch с сопоставление с образцом для определения типа удобно:

Пример:

protocol SomeProtocol: class {}

class A {
    let foo = 17
}
extension A: SomeProtocol {}
class B {
    let bar = "hello"
}
extension B: SomeProtocol {}
class C {
    let baz = true
}
extension C: SomeProtocol {}
class D: SomeProtocol {}

let arr: [SomeProtocol] = [D(), A(), C(), B()]

for object in arr {
    switch object {
    case let a as A:
        print("object is A")
        print(a.foo)
    case let b as B:
        print("object is B")
        print(b.bar)
    case let c as C:
        print("object is C")
        print(c.baz)
    default:
        print("object is some other type")
    }
}

Выход:

object is some other type
object is A
17
object is C
true
object is B
hello
2 голосов
/ 02 октября 2019

Вы можете использовать case let, чтобы немного его почистить. Если взять приведенный выше пример, его можно изменить на

protocol SomeProtocol: class {}

class A {}
extension A: SomeProtocol {}
class B {}
extension B: SomeProtocol {}
class C {}
extension C: SomeProtocol {}

let arr: [SomeProtocol] = [A(), B(), C()]

for case let object as A in arr {
    print("item is A")
}

. Это будет циклически проходить по массиву, и если элемент может быть приведен к указанному типу, будет выполнено тело цикла for. Он просто удаляет строку вложенности и выглядит немного чище, хотя в конечном итоге он совпадает с ответом Sweeper выше

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...