Programing

Swift에서 "포장 해제 된 값"은 무엇입니까?

lottogame 2020. 6. 7. 00:41
반응형

Swift에서 "포장 해제 된 값"은 무엇입니까?


이 튜토리얼 을 따라 iOS 8 / OSX 10.10 용 Swift를 배우고 있으며이 단락 ( Objects and Class 아래)에서와 같이 " unwrapped value " 라는 단어 가 여러 번 사용됩니다 .

선택적 값으로 작업 할 때?를 쓸 수 있습니다. 메서드, 속성 및 첨자 같은 작업 전에 만약 앞에 값이? nil, 이후의 모든 것? 무시되고 전체 표현식의 값은 nil입니다. 그렇지 않으면 선택적 값이 래핑되지 않고? 래핑되지 않은 값 에 작용 합니다 . 두 경우 모두 전체 표현식의 값은 선택적 값입니다.

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare?.sideLength

나는 그것을 얻지 못하고 운없이 웹에서 검색했습니다.

이것은 무엇을 의미합니까?


편집하다

Cezary의 답변에서 원본 코드의 출력과 최종 솔루션 (놀이터에서 테스트)에는 약간의 차이가 있습니다.

원본 코드

원본 코드

세자리의 솔루션

세자리의 솔루션

수퍼 클래스의 속성은 두 번째 경우의 출력에 표시되고 첫 번째 경우에는 빈 개체가 있습니다.

두 경우 모두 결과가 동일하지 않습니까?

관련 Q & A : Swift의 선택적 값은 무엇입니까?


먼저 선택적 유형이 무엇인지 이해해야합니다. 선택적 유형은 기본적으로 변수 가 될 수 있음을 의미 합니다nil .

예:

var canBeNil : Int? = 4
canBeNil = nil

물음표는 사실 일 canBeNil수 있습니다 nil.

이것은 작동하지 않습니다 :

var cantBeNil : Int = 4
cantBeNil = nil // can't do this

선택 사항 인 경우 변수에서 값을 가져 오려면 해제해야합니다 . 이것은 단지 느낌표를 마지막에 두는 것을 의미합니다.

var canBeNil : Int? = 4
println(canBeNil!)

코드는 다음과 같아야합니다.

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare!.sideLength

주석 :

물음표 대신 느낌표를 사용하여 자동으로 줄 바꿈 해제 옵션을 선언 할 수도 있습니다.

예:

var canBeNil : Int! = 4
print(canBeNil) // no unwrapping needed

따라서 코드를 수정하는 다른 방법은 다음과 같습니다.

let optionalSquare: Square! = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare.sideLength

편집하다:

당신이보고있는 차이점은 정확히 선택적 값이 포장 되어 있다는 사실의 증상입니다 . 그 위에 다른 레이어가 있습니다. 미개봉 는, 음, 미개봉 때문에 버전은 직선 객체를 보여줍니다.

빠른 놀이터 비교 :

운동장

In the first and second cases, the object is not being automatically unwrapped, so you see two "layers" ({{...}}), whereas in the third case, you see only one layer ({...}) because the object is being automatically unwrapped.

The difference between the first case and the second two cases is that the second two cases will give you a runtime error if optionalSquare is set to nil. Using the syntax in the first case, you can do something like this:

if let sideLength = optionalSquare?.sideLength {
    println("sideLength is not nil")
} else {
    println("sidelength is nil")
}

The existing correct answer is great, but I found that for me to understand this fully, I needed a good analogy, since this is a very abstract and weird concept.

So, let me help those fellow "right-brained" (visual thinking) developers out by giving a different perspective in addition to the correct answer. Here is a good analogy that helped me a lot.

Birthday Present Wrapping Analogy

Think of optionals as being like birthday presents that come in stiff, hard, colored wrapping.

You don't know if there's anything inside the wrapping until you unwrap the present — maybe there is nothing at all inside! If there is something inside, it could be yet another present, which is also wrapped, and which also might contain nothing. You might even unwrap 100 nested presents to finally discover there was nothing but wrapping.

If the value of the optional is not nil, now you have revealed a box containing something. But, especially if the value is not explicitly typed and is a variable and not a predefined constant, then you may still need to open the box before you can know anything specific about what's in the box, like what type it is, or what the actual value is.

What's In The Box?! Analogy

Even after you unwrap the variable, you are still like Brad Pitt in the last scene in SE7EN (warning: spoilers and very R-rated foul language and violence), because even after you have unwrapped the present, you are in the following situation: you now have nil, or a box containing something (but you don't know what).

You might know the type of the something. For example, if you declared the variable as being type, [Int:Any?], then you'd know you had a (potentially empty) Dictionary with integer subscripts that yield wrapped contents of any old type.

That is why dealing with collection types (Dictionaries and Arrays) in Swift can get kind of hairy.

Case in point:

typealias presentType = [Int:Any?]

func wrap(i:Int, gift:Any?) -> presentType? {
    if(i != 0) {
        let box : presentType = [i:wrap(i-1,gift:gift)]
        return box
    }
    else {
        let box = [i:gift]
        return box
    }
}

func getGift() -> String? {
    return "foobar"
}

let f00 = wrap(10,gift:getGift())

//Now we have to unwrap f00, unwrap its entry, then force cast it into the type we hope it is, and then repeat this in nested fashion until we get to the final value.

var b4r = (((((((((((f00![10]! as! [Int:Any?])[9]! as! [Int:Any?])[8]! as! [Int:Any?])[7]! as! [Int:Any?])[6]! as! [Int:Any?])[5]! as! [Int:Any?])[4]! as! [Int:Any?])[3]! as! [Int:Any?])[2]! as! [Int:Any?])[1]! as! [Int:Any?])[0])

//Now we have to DOUBLE UNWRAP the final value (because, remember, getGift returns an optional) AND force cast it to the type we hope it is

let asdf : String = b4r!! as! String

print(asdf)

Swift places a high premium on type safety. The entire Swift language was designed with safety in mind. It is one of the hallmarks of Swift and one that you should welcome with open arms. It will assist in the development of clean, readable code and help keep your application from crashing.

All optionals in Swift are demarcated with the ? symbol. By setting the ? after the name of the type in which you are declaring as optional you are essentially casting this not as the type in which is before the ?, but instead as the optional type.


Note: A variable or type Int is not the same as Int?. They are two different types that can not be operated on each other.


Using Optional

var myString: String?

myString = "foobar"

This does not mean that you are working with a type of String. This means that you are working with a type of String? (String Optional, or Optional String). In fact, whenever you attempt to

print(myString)

at runtime, the debug console will print Optional("foobar"). The "Optional()" part indicates that this variable may or may not have a value at runtime, but just so happens to currently be containing the string "foobar". This "Optional()" indication will remain unless you do what is called "unwrapping" the optional value.

Unwrapping an optional means that you are now casting that type as non-optional. This will generate a new type and assign the value that resided within that optional to the new non-optional type. This way you can perform operations on that variable as it has been guaranteed by the compiler to have a solid value.


Conditionally Unwrapping will check if the value in the optional is nil or not. If it is not nil, there will be a newly created constant variable that will be assigned the value and unwrapped into the non-optional constant. And from there you may safely use the non-optional in the if block.

Note: You can give your conditionally unwrapped constant the same name as the optional variable you are unwrapping.

if let myString = myString {
    print(myString)
    // will print "foobar"
}

Conditionally unwrapping optionals is the cleanest way to access an optional's value because if it contains a nil value then everything within the if let block will not execute. Of course, like any if statement, you may include an else block

if let myString = myString {
    print(myString)
    // will print "foobar"
}
else {
    print("No value")
}

Forcibly Unwrapping is done by employing what is known as the ! ("bang") operator. This is less safe but still allows your code to compile. However whenever you use the bang operator you must be 1000% certain that your variable does in fact contain a solid value before forcibly unwrapping.

var myString: String?

myString = "foobar"

print(myString!)

This above is entirely valid Swift code. It prints out the value of myString that was set as "foobar". The user would see foobar printed in the console and that's about it. But let's assume the value was never set:

var myString: String?

print(myString!) 

Now we have a different situation on our hands. Unlike Objective-C, whenever an attempt is made to forcibly unwrap an optional, and the optional has not been set and is nil, when you try to unwrap the optional to see what's inside your application will crash.


Unwrapping w/ Type Casting. As we said earlier that while you are unwrapping the optional you are actually casting to a non-optional type, you can also cast the non-optional to a different type. For example:

var something: Any?

Somewhere in our code the variable something will get set with some value. Maybe we are using generics or maybe there is some other logic that is going on that will cause this to change. So later in our code we want to use something but still be able to treat it differently if it is a different type. In this case you will want to use the as keyword to determine this:

Note: The as operator is how you type cast in Swift.

// Conditionally
if let thing = something as? Int {
    print(thing) // 0
}

// Optionally
let thing = something as? Int
print(thing) // Optional(0)

// Forcibly
let thing = something as! Int
print(thing) // 0, if no exception is raised

Notice the difference between the two as keywords. Like before when we forcibly unwrapped an optional we used the ! bang operator to do so. Here you will do the same thing but instead of casting as just a non-optional you are casting it also as Int. And it must be able to be downcast as Int, otherwise, like using the bang operator when the value is nil your application will crash.

And in order to use these variables at all in some sort or mathematical operation they must be unwrapped in order to do so.

For instance, in Swift only valid number data types of the same kind may be operated on each other. When you cast a type with the as! you are forcing the downcast of that variable as though you are certain it is of that type, therefore safe to operate on and not crash your application. This is ok as long as the variable indeed is of the type you are casting it to, otherwise you'll have a mess on your hands.

Nonetheless casting with as! will allow your code to compile. By casting with an as? is a different story. In fact, as? declares your Int as a completely different data type all together.

Now it is Optional(0)

And if you ever tried to do your homework writing something like

1 + Optional(1) = 2

당신의 수학 교사는 아마도 당신에게 "F"를 주었을 것입니다. 스위프트와 동일합니다. 스위프트를 제외하고는 등급을 부여하는 것보다는 컴파일하지 않을 것입니다. 하루가 끝나면 선택 사항은 실제로 nil 일 수 있습니다 .

안전 제일 아이들.


'?' 선택적인 연쇄 표현을 ​​의미

합니다. '!'는 힘의 가치입니다.
여기에 이미지 설명을 입력하십시오

참고 URL : https://stackoverflow.com/questions/24034483/what-is-an-unwrapped-value-in-swift

반응형