sourcecode

Swift에서 옵션 다운캐스팅: as?타이프, or as!타입?

copyscript 2023. 9. 6. 22:14
반응형

Swift에서 옵션 다운캐스팅: as?타이프, or as!타입?

스위프트에서 다음과 같은 것이 주어집니다.

var optionalString: String?
let dict = NSDictionary()

다음 두 문장의 실제적인 차이점은 무엇입니까?

optionalString = dict.objectForKey("SomeKey") as? String

optionalString = dict.objectForKey("SomeKey") as! String?

실제적인 차이점은 다음과 같습니다.

var optionalString = dict["SomeKey"] as? String

optionalString는 유형가될의e의 변수가 될 입니다.String?이 a가 . 이 a 인 인 이 String이것은 해롭지 않게 그냥 할당할 것입니다.nil

var optionalString = dict["SomeKey"] as! String?

이런 말이 있어요, 이건...String?. 이 또한 결과를 초래할 것입니다.optionalStringString?, 하지만 기본 유형이 다른 유형이면 충돌합니다.

번째 은 은 과 됩니다 됩니다 과 와 함께 사용됩니다.if let옵션의 포장을 안전하게 벗깁니다.

if let string = dict["SomeKey"] as? String {
    // If I get here, I know that "SomeKey" is a valid key in the dictionary, I correctly
    // identified the type as String, and the value is now unwrapped and ready to use.  In
    // this case "string" has the type "String".
    print(string)
}

as? Types합니다. -팅임을다은다임을은s팅e-sg .프로세스가 성공할 수도 있고 그렇지 않을 수도 있습니다(다운캐스팅이 실패하면 시스템이 0으로 반환됩니다).다운캐스팅이 실패해도 어떤 방법으로도 충돌하지 않습니다.

as! Type?서 다운캐스팅 서팅야다가(다야e가팅e서edfg!것을 e)nstgn)ter.l )종료 물음표는 최종 결과가 0이 될 수 있는지 여부를 나타냅니다.

"!" 및 "?"에 대한 자세한 정보

두 가지 사례를 들어보겠습니다.

  1. 고려 사항:

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell
    

    여기서는 식별자가 "Cell"인 셀을 UITableViewCell로 다운캐스팅한 결과가 성공했는지 여부를 알 수 없습니다.실패하면 0으로 반환됩니다(따라서 여기서는 충돌을 방지합니다).여기서 우리는 아래와 같이 할 수 있습니다.

    if let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell {
        // If we reached here it means the down casting was successful
    }
    else {
        // unsuccessful down casting
    }
    

    그럼 이렇게 기억합시다 - 만약에?그것은 우리가 가치가 0인지 아닌지 확신할 수 없다는 것을 의미합니다. (물건을 모를 때 물음표가 나타납니다.)

  2. 다음과 비교:

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell. 
    

    여기서 우리는 컴파일러에게 다운캐스팅이 성공적이어야 한다고 말합니다.실패할 경우 시스템이 충돌합니다.그래서 저희가.!값이 0이 아니라고 확신할 때.

바카와마가 말한 것을 명확히 하기 위해, 여기 예가 있습니다.

스위프트 3.0:

import UIKit

let str_value:    Any   = String("abc")!
let strOpt_value: Any?  = String("abc")!
let strOpt_nil:   Any?  = (nil as String?)
let int_value:    Any   = Int(1)
let intOpt_value: Any?  = Int(1)
let intOpt_nil:   Any?  = (nil as Int?)

// as String
//str_value     as String // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//strOpt_value  as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//strOpt_nil    as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//int_value     as String // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//intOpt_value  as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//intOpt_nil    as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?

// as? String
  str_value     as? String // == "abc"
  strOpt_value  as? String // == "abc"
  strOpt_nil    as? String // == nil
  int_value     as? String // == nil
  intOpt_value  as? String // == nil
  intOpt_nil    as? String // == nil

// as! String
  str_value     as! String // == "abc"
  strOpt_value  as! String // == "abc"
//strOpt_nil    as! String // Run-Time Error: unexpectedly found nil while unwrapping an Optional value.
//int_value     as! String // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
//intOpt_value  as! String // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
//intOpt_nil    as! String // Run-Time Error: unexpectedly found nil while unwrapping an Optional value.

// as String?
//str_value     as String? // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
//strOpt_value  as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
//strOpt_nil    as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
//int_value     as String? // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
//intOpt_value  as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
//intOpt_nil    as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?

// as? String?
//str_value     as? String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
  strOpt_value  as? String? // == "abc"
  strOpt_nil    as? String? // == nil
//int_value     as? String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
  intOpt_value  as? String? // == nil
  intOpt_nil    as? String? // == nil

// as! String?
//str_value     as! String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
  strOpt_value  as! String? // == "abc"
  strOpt_nil    as! String? // == nil
//int_value     as! String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
//intOpt_value  as! String? // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
  intOpt_nil    as! String? // == nil

// let _ = ... as String
//if let _ = str_value    as String { true } // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//if let _ = strOpt_value as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//if let _ = strOpt_nil   as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//if let _ = int_value    as String { true } // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//if let _ = intOpt_value as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
//if let _ = intOpt_nil   as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?

// let _ = ... as? String
if let _ = str_value    as? String { true } // true
if let _ = strOpt_value as? String { true } // true
if let _ = strOpt_nil   as? String { true } // false
if let _ = int_value    as? String { true } // false
if let _ = intOpt_value as? String { true } // false
if let _ = intOpt_nil   as? String { true } // false

// let _ = ... as! String
//if let _ = str_value    as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
//if let _ = strOpt_value as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
//if let _ = strOpt_nil   as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
//if let _ = int_value    as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
//if let _ = intOpt_value as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
//if let _ = intOpt_nil   as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'

// let _ = ... as String?
//if let _ = str_value    as String? { true } // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
//if let _ = strOpt_value as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
//if let _ = strOpt_nil   as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
//if let _ = int_value    as String? { true } // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
//if let _ = intOpt_value as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
//if let _ = intOpt_nil   as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?

// let _ = ... as? String?
//if let _ = str_value    as? String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
  if let _ = strOpt_value as? String? { true } // true
  if let _ = strOpt_nil   as? String? { true } // true
//if let _ = int_value    as? String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
  if let _ = intOpt_value as? String? { true } // false
  if let _ = intOpt_nil   as? String? { true } // true

// let _ = ... as! String?
//if let _ = str_value    as! String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
  if let _ = strOpt_value as! String? { true } // true
  if let _ = strOpt_nil   as! String? { true } // false
//if let _ = int_value    as! String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
//if let _ = intOpt_value as! String? { true } // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
  if let _ = intOpt_nil   as! String? { true } // false

스위프트 2.0:

import UIKit

let str:    AnyObject   = String("abc")
let strOpt: AnyObject?  = String("abc")
let strNil: AnyObject?  = (nil as String?)
let int:    AnyObject   = Int(1)
let intOpt: AnyObject?  = Int(1)
let intNil: AnyObject?  = (nil as Int?)

str    as? String // == "abc"
strOpt as? String // == "abc"
strNil as? String // == nil
int    as? String // == nil
intOpt as? String // == nil
intNil as? String // == nil

str    as! String? // Compile-Time Error: Cannot downcast from 'AnyObject' to a more optional type 'String?'
strOpt as! String? // == "abc"
strNil as! String? // == nil
int    as! String? // Compile-Time Error: Cannot downcast from 'AnyObject' to a more optional type 'String?'
intOpt as! String? // Run-Time Error: Could not cast value of type '__NSCFNumber' to 'NSString'
intNil as! String? // == nil
  • as 및 주조에 형팅용로용로및팅서ddor형gp
  • as?주조를 되며, 실패할 경우 합니다.용우환로할전으로 0환우0
  • as! 주조, 시 됨우돌할제돌우할에do,됨efg

참고:

  • as!미가공 유형을 선택 사항으로 지정할 수 없음

예:

let rawString: AnyObject = "I love swift"
let optionalString: AnyObject? = "we love swift"
let nilString: AnyObject? = (nil as String?)

let rawInt: AnyObject = Int(3)
let optionalInt: AnyObject? = Int(3)
let nilInt: AnyObject? = (nil as Int?)

var age: Int? = nil
var height: Int? = 180

데이터 유형 바로 뒤에 ?를 추가하면 컴파일러에 변수에 숫자가 포함될 수도 있고 포함되지 않을 수도 있음을 알 수 있습니다.깔끔합니다! 옵션 상수를 정의하는 것은 의미가 없습니다. 값을 한 번만 설정할 수 있으므로 값이 0인지 여부를 말할 수 있습니다.

"?"를 사용해야 할 때와 "!"를 사용해야 할 때.

UIKit 기반의 간단한 앱이 있다고 치자.우리는 뷰 컨트롤러에 코드가 있고 그 위에 새로운 뷰 컨트롤러를 제시하고 싶습니다. 그리고 우리는 네비게이션 컨트롤러를 사용하여 화면에 새로운 뷰를 푸시하기로 결정해야 합니다.

모든 ViewController 인스턴스에는 속성 탐색 컨트롤러가 있습니다.탐색 컨트롤러 기반 앱을 구축하는 경우 앱의 마스터 보기 컨트롤러 속성이 자동으로 설정되며 이 속성을 사용하여 보기 컨트롤러를 누르거나 팝업할 수 있습니다.단일 앱 프로젝트 템플릿을 사용하는 경우 자동으로 생성되는 탐색 컨트롤러가 없으므로 앱의 기본 보기 컨트롤러에는 탐색 컨트롤러 속성에 저장된 내용이 없습니다.

이것이 바로 선택 데이터 유형의 경우라는 것을 이미 짐작하셨을 것입니다.UIViewController를 선택하면 속성이 다음과 같이 정의됩니다.

var navigationController: UINavigationController? { get }

자, 다시 사용 사례로 돌아가 보겠습니다.보기 컨트롤러에 항상 네비게이션 컨트롤러가 있음을 알고 있다면 다음과 같이 강제로 포장을 해제할 수 있습니다.

controller.navigationController!.pushViewController(myViewController, animated: true)

속성 이름 뒤에 !를 붙이면 컴파일러에 이 속성이 옵션인 것은 상관하지 않습니다. 이 코드가 실행되면 항상 저장소가 존재한다는 것을 알고 있으므로옵션을 일반 데이터 유형처럼 취급합니다.그거 좋지 않아요?보기 컨트롤러에 네비게이션 컨트롤러가 없으면 어떻게 됩니까?navigationController에 저장된 값이 항상 있을 것이라고 제안하는 경우 잘못된 것입니까?앱이 다운됩니다.그렇게 단순하고 추한.

따라서 101%로 안전하다고 확신하는 경우에만 !을 사용하십시오.

내비게이션 컨트롤러가 항상 있을 것이라고 확신할 수 없다면 어떨까요?그러면 ! 대신 ?을 사용할 수 있습니다.

controller.navigationController?.pushViewController(myViewController, animated: true)

속성 이름 뒤에 있는 ?가 컴파일러에게 알려주는 은 이 속성에 0이 포함되어 있는지 값이 포함되어 있는지 알 수 없으므로 값이 있으면 사용하고, 그렇지 않으면 전체 식을 0으로 간주합니다.사실상 ?를 사용하면 네비게이션 컨트롤러가 있는 경우에도 해당 속성을 사용할 수 있습니다.어떤 종류의 수표나 어떤 종류의 주조물이라도 상관없습니다.이 구문은 네비게이션 컨트롤러가 있든 없든 상관없이 원하는 경우에만 사용할 수 있습니다.

Fantageek 덕분입니다.

스위프트에서 다운캐스팅의 두 가지 다른 형태입니다.

() 조건부 양식으로 알려져 있으며 다운캐스트하려는 유형의 선택적 값을 반환합니다.as?

다운캐스트 성공 여부가 확실하지 않을 때 사용할 수 있습니다.이 연산자 형식은 항상 옵션 값을 반환하며 다운캐스트가 불가능한 경우에는 값이 0이 됩니다.이렇게 하면 다운캐스트가 성공했는지 확인할 수 있습니다.


()는 Forced Form으로 알려져 있으며 다운캐스트를 시도하고 단일 복합 작용으로 결과를 강제로 언랩합니다.as!

다운캐스트가 항상 성공할 것이라고 확신하는 경우에만 사용해야 합니다.잘못된 클래스 유형으로 다운캐스트를 시도하면 이 연산자 형식이 런타임 오류를 트리거합니다.

자세한 사항은 Apple 문서의 Type Casting 섹션을 참조하십시오.

아마도 이 코드 예시는 누군가가 원칙을 이해하는 데 도움이 될 것입니다.

var dict = [Int:Any]()
dict[1] = 15

let x = dict[1] as? String
print(x) // nil because dict[1] is an Int

dict[2] = "Yo"

let z = dict[2] as! String?
print(z) // optional("Yo")
let zz = dict[1] as! String // crashes because a forced downcast fails


let m = dict[3] as! String?
print(m) // nil. the forced downcast succeeds, but dict[3] has no value

번째는 '조건부 캐스팅'(제가 연결한 문서의 '타입캐스팅 사업자' 아래 참조)입니다.캐스트가 성공하면 식의 값이 선택 사항으로 래핑되어 반환되고, 그렇지 않으면 반환되는 값이 0이 됩니다.

두 번째는 선택적 String이 문자열 개체이거나 0일 수 있음을 의미합니다.

이와 관련된 질문에서 보다 자세한 내용을 확인할 수 있습니다.

Swift에서 이러한 연산자의 패턴을 다음과 같이 기억하는 것이 가장 쉬울 수 있습니다.!"이것은 함정에 빠질 수 있다"고 암시하는 반면?"이것은 0일 수 있습니다."를 나타냅니다.

참조: https://developer.apple.com/swift/blog/ ?id=23

저는 스위프트가 처음이고 '옵션'에 대해 이해하는 것처럼 설명하려고 이 예시를 씁니다.제가 틀렸다면 고쳐주세요.

감사해요.


class Optional {

    var lName:AnyObject! = "1"

    var lastName:String!
}

let obj = Optional()

print(obj.lName)

print(obj.lName!)

obj.lastName = obj.lName as? String

print(obj.lastName)

(1) :obj.lastName = obj.lName as! String

(2) :obj.lastName = obj.lName as? String

Ans : (1) 여기 프로그래머는 확실히“obj.lName”문자열 유형 개체를 포함합니다.그래서 그 가치를 그냥.“obj.lastName”.

이제, 프로그래머가 올바른 의미라면"obj.lName"string type 개체입니다. 그러면 문제 없습니다."obj.lastName"은(는) 동일한 값으로 설정됩니다.

하지만 프로그래머가 틀리면 다음을 의미합니다."obj.lName"는 문자열 유형 개체가 아닙니다. 즉, "NSNumber" 등과 같은 다른 유형 개체를 포함합니다.그런 다음 CRASH(Run Time Error)를 실행합니다.

(2) 프로그래머는 확신할 수 없습니다.“obj.lName”문자열 유형 개체 또는 기타 유형 개체를 포함합니다.따라서 이 값을 다음으로 설정합니다.“obj.lastName”문자열 유형인 경우.

, 가 라면 을 합니다.“obj.lName”문자열 타입 개체입니다 그러면 문제 없습니다.“obj.lastName”는 동일한 값으로 설정됩니다.

하지만 프로그래머가 틀리면 obj를 의미합니다.lName이 문자열 유형 개체가 아닙니다. 즉 다음과 같은 다른 유형 개체를 포함합니다."NSNumber"그 외에. 그다음에.“obj.lastName”는 0 값으로 설정됩니다. Crash (서, No Crash (해피:)

언급URL : https://stackoverflow.com/questions/25708649/downcasting-optionals-in-swift-as-type-or-as-type

반응형