for-in 루프에서 유형 캐스팅


116

이 for-in 루프가 있습니다.

for button in view.subviews {
}

이제 버튼을 사용자 정의 클래스로 캐스팅하여 속성을 사용할 수 있도록합니다.

나는 이것을 시도했다 : for button in view.subviews as AClass

하지만 작동하지 않고 오류가 발생합니다.'AClass' does not conform to protocol 'SequenceType'

그리고 나는 이것을 시도했다. for button:AClass in view.subviews

그러나 그것은 작동하지 않습니다.


어떻습니까for button in view.subviews as [AClass]
vacawama 2014 년

2
하하 나는 그것을 생각하지 않았고, 물론 배열을 AClass 배열로 캐스팅하는 것이 더 낫습니다. 감사합니다. 내가 당신에게 담당자 : 줄 수 있도록 그것에 대해 답변을 할 수 있습니다
Arbitur

답변:


173

대한 스위프트 2 이상 및 :

스위프트 2는 추가 의 경우 패턴대한 더욱 쉽게하고 더 안전에 캐스트를 입력 할 수있는 루프 에 대한 루프 :

for case let button as AClass in view.subviews {
    // do something with button
}

Swift 1.2 및 이전 버전 에서 할 수있는 것보다 이것이 왜 더 나은 가요? 때문에 경우 패턴 은 컬렉션에서 특정 유형을 선택할 수 있습니다. 찾고있는 유형과 만 일치하므로 배열에 혼합이 포함되어 있으면 특정 유형에서만 작동 할 수 있습니다.

예를 들면 :

let array: [Any] = [1, 1.2, "Hello", true, [1, 2, 3], "World!"]
for case let str as String in array {
    print(str)
}

산출:

Hello
World!

대한 스위프트 1.2 :

이 경우에는 캐스트 view.subviews가 아닌 button캐스트이므로 원하는 유형의 배열로 다운 캐스트해야합니다.

for button in view.subviews as! [AClass] {
    // do something with button
}

참고 : 기본 배열 유형이가 아닌 [AClass]경우 충돌이 발생합니다. 즉, 무엇 !에가 as!당신을 말하고있다. 유형에 대해 확실하지 않은 경우 as?선택적 바인딩과 함께 조건부 캐스트 를 사용할 수 있습니다 if let.

if let subviews = view.subviews as? [AClass] {
    // If we get here, then subviews is of type [AClass]
    for button in subviews {
        // do something with button
    }
}

대한 스위프트 1.1 및 이전 버전 :

for button in view.subviews as [AClass] {
    // do something with button
}

참고 : 하위보기가 모든 유형이 아닌 경우에도 충돌이 발생합니다 AClass. 위에 나열된 안전한 방법은 이전 버전의 Swift에서도 작동합니다.


처음에는 이해하지 못한 저와 같은 다른 사람들을위한 메모입니다. 클래스 이름은 [ ]이 예제에서와 같이 괄호 안에 넣어야 합니다. 어쩌면 그것은 나일지도 모르지만 처음에는 코드 샘플에서 형식 지정 선택이라고 생각했습니다. :) 우리가 배열로 캐스팅하기 때문이라고 생각합니다.

@kmcgrady 그것 [Class]보다 훨씬 좋아 보인다 Array<Class>.
Arbitur

그래서 호기심에서 for 루프 내에서 여러 case 문을 수행하는 방법이 있습니까? 예를 들어 버튼에 한 가지 작업을하고 텍스트 필드에 다른 작업을 수행하려면?
RonLugge 2017

125

이 옵션은 더 안전합니다.

for case let button as AClass in view.subviews {
}

또는 신속한 방법 :

view.subviews
  .compactMap { $0 as AClass }
  .forEach { .... }

1
포스 캐스트가 없기 때문에 이것은 더 좋은 대답처럼 보입니다.
Patrick

1
이것은 받아 들여진 대답이어야합니다. 가장 좋은 것이고 올바른 것입니다!
Thomás Calmon

정답입니다. 짧고 간단합니다.
PashaN

4

where절을 사용할 수도 있습니다.

for button in view.subviews where button is UIButton {
    ...
}

12
where 절은 부울 가드이지만 button다른 솔루션의 목표 인 루프 본문 내부의 유형을 캐스팅하지 않습니다 . 따라서 이것은 요소 view.subviewsUIButtons 인 루프 본문 만 실행 하지만에서 AClass특정 메서드를 호출하는 데는 도움이되지 않습니다 button.
John Whitley

1
@JohnWhitley 당신은 where가드 만하고 캐스팅하지 않는 것이 맞습니다 .
edelaney05

where부울 가드 만 필요한 경우 (의도하지 않은 말장난)의 경우 더 우아하고 읽기 쉬울 수 있습니다.
STO

3

제공된 답변이 정확합니다. 추가로 추가하고 싶었습니다.

강제 캐스팅과 함께 for 루프를 사용하면 코드가 충돌합니다 (다른 사람들이 이미 언급했듯이).

for button in view.subviews as! [AClass] {
    // do something with button
}

하지만 if 절을 사용하는 대신

if let subviews = view.subviews as? [AClass] {
    // If we get here, then subviews is of type [AClass]
    ...
}

또 다른 방법은 while 루프를 사용하는 것입니다.

/* If you need the index: */
var iterator = view.subviews.enumerated().makeIterator()
while let (index, subview) = iterator.next() as? (Int, AClass) {
    // Use the subview
    // ...
}

/* If you don't need the index: */
var iterator = view.subviews.enumerated().makeIterator()
while let subview = iterator.next().element as? AClass {
    // Use the subview
    // ...
}

배열의 일부 요소 (전체는 아님)가 유형 일 수 있다면 더 편리해 보입니다 AClass.

지금은 (Swift 5 기준) for-case 루프를 사용합니다.

for case let (index, subview as AClass) in view.subviews.enumerated() {
    // ...
}

for case let subview as AClass in view.subviews {
    // ...
}

여기에 한 가지 의심이 있습니다 ... 빠른 열거 함수가 여기에서 반복 / 루프를 수행합니까 .. 성능 저하에 대한 리팩토링이 좋지 않을 것이라고 생각하는 것뿐입니다 ... 감사합니다
Amber K

2

vacawama가 제공 한 답변은 Swift 1.0에서 정확했습니다. 그리고 더 이상 Swift 2.0에서 작동하지 않습니다.

시도하면 다음과 유사한 오류가 발생합니다.

'[AnyObject]'는 '[AClass]'로 변환 할 수 없습니다.

Swift 2.0에서는 다음과 같이 작성해야합니다.

for button in view.subviews as! [AClass]
{
}

0

다음과 같이 캐스팅을 수행하고 동시에 안전 할 수 있습니다.

for button in view.subviews.compactMap({ $0 as? AClass }) {

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.