Swift의 선택적 값은 무엇입니까?


267

에서 애플의 설명서 :

및를 함께 사용 if하여 let누락 될 수있는 값으로 작업 할 수 있습니다. 이 값은 옵션으로 표시됩니다. 선택적 값은 값을 포함하거나 nil값이 누락되었음을 표시하기 위해 포함 합니다. ?값 유형 뒤에 물음표 ( )를 써서 값을 옵션으로 표시하십시오.

왜 선택적 값을 사용하고 싶습니까?



1
옵션은 옵션 / 어쩌면 모나드 의 구현으로 볼 수도 있습니다 . 이 블로그 는 어려운 개념이 무엇인지 설명하려고 노력합니다.
StuartLC

tldr : "Swift를 사용하면 값이 누락 될 수있는 시점과 존재하는 시점을 명확하게 파악해야합니다." nevan king의 탁월한 답변 아래
jonatan

답변:


531

Swift의 옵션은 값을 보유하거나 보유하지 않는 유형입니다. 옵션은 ?모든 유형에 a 를 추가하여 작성됩니다 .

var name: String? = "Bertie"

선택 사항 (제네릭과 함께)은 이해하기 가장 어려운 Swift 개념 중 하나입니다. 그것들이 어떻게 작성되고 사용되는지에 따라, 그들이 무엇인지 잘못 이해하기 쉽습니다. 위의 옵션을 비교하여 일반 문자열을 만듭니다.

var name: String = "Bertie" // No "?" after String

구문에서 선택적 String은 일반 String과 매우 유사합니다. 그렇지 않습니다. 선택적 문자열은 일부 "선택적"설정이 설정된 문자열이 아닙니다. 특별한 다양한 문자열이 아닙니다. 문자열과 선택적 문자열은 완전히 다른 유형입니다.

알아야 할 가장 중요한 사항은 다음과 같습니다. 옵션은 일종의 컨테이너입니다. 선택적 String은 String을 포함 할 수있는 컨테이너입니다. 선택적 Int는 Int를 포함 할 수있는 컨테이너입니다. 선택 사항을 일종의 소포로 생각하십시오. 당신이 그것을 열기 전에 (또는 선택의 언어로 "포장 풀기") 당신은 그것이 무엇인가 포함되어 있는지 알 수 없습니다.

Swift 파일에 "선택 사항"을 입력하고 ⌘- 클릭하면 Swift 표준 라이브러리에서 선택 사항이 어떻게 구현되는지 확인할 수 있습니다 . 정의의 중요한 부분은 다음과 같습니다.

enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}

옵션은 단지입니다 enum이가지 경우 하나가 될 수있다 : .none.some. 이 경우 .some위의 예에서 String"Hello" 가되는 관련 값이 있습니다 . 선택 사항은 Generics를 사용하여 연관된 값에 유형을 제공합니다. 옵션 문자열의 형식은 아닙니다 String그것의, Optional또는 더 정확하게 Optional<String>.

Swift가 옵션을 사용하여 수행하는 모든 작업은 읽기 및 쓰기 코드를보다 유창하게 만드는 마법입니다. 불행히도 이것은 실제로 작동하는 방식을 모호하게합니다. 나중에 몇 가지 요령을 살펴 보겠습니다.

참고 : 선택적 변수에 대해 많이 이야기 할 것이지만 선택적 상수도 만드는 것이 좋습니다. 생성되는 유형 유형을 이해하기 쉽도록 모든 변수를 유형으로 표시하지만 자신의 코드에는 필요하지 않습니다.


옵션을 만드는 방법

선택 사항을 만들려면 ?줄 바꿈하려는 유형 뒤에를 추가하십시오 . 모든 유형은 선택 사항 일 수 있으며 심지어 자신의 사용자 정의 유형일 수도 있습니다. 유형과 사이에 공백을 둘 수 없습니다 ?.

var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)

// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}

옵션 사용

선택 사항을 비교하여 nil값이 있는지 확인할 수 있습니다 .

var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
    print("There is a name")
}
if name == nil { // Could also use an "else"
    print("Name has no value")
}

약간 혼란 스럽다. 선택 사항은 하나 또는 다른 것임을 의미합니다. nil이거나 "Bob"입니다. 이것은 사실이 아니며, 옵션은 다른 것으로 변형되지 않습니다. 코드를 nil과 비교하는 것은 읽기 쉬운 코드를 만드는 속임수입니다. 선택 사항이 nil 인 경우 열거 형이 현재로 설정되어 있음을 의미합니다 .none.


옵션 만 사용할 수 있습니다

비 선택적 변수를 nil로 설정하려고하면 오류가 발생합니다.

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'

옵션을 보는 또 다른 방법은 일반적인 Swift 변수를 보완하는 것입니다. 그것들은 값을 갖도록 보장되는 변수에 대응합니다. 스위프트는 모호성을 싫어하는 신중한 언어입니다. 대부분의 변수는 옵션이 아닌 것으로 정의되지만 때로는 불가능합니다. 예를 들어, 캐시 또는 네트워크에서 이미지를로드하는 뷰 컨트롤러를 상상해보십시오. 뷰 컨트롤러가 생성 될 때 이미지가있을 수도 있고 없을 수도 있습니다. 이미지 변수의 값을 보장 할 방법이 없습니다. 이 경우 선택 사항으로 만들어야합니다. nil이미지가 검색 될 때 시작되고 옵션이 값을 가져옵니다.

옵션을 사용하면 프로그래머의 의도가 드러납니다. 객체가 없을 수있는 Objective-C와 비교하여 Swift는 값이 누락 될 수있는 시점과 존재가 보장되는 시점을 명확히해야합니다.


옵션을 사용하려면 "포장 풀기"

String실제 위치 대신 옵션을 사용할 수 없습니다 String. 래핑 된 값을 옵션 내에서 사용하려면 래핑 해제해야합니다. 선택 사항을 랩핑 해제하는 가장 간단한 방법 !은 선택적 이름 다음 에 추가하는 것입니다. 이것을 "강제 풀기"라고합니다. 선택 사항 내부의 값 (원래 유형으로)을 리턴하지만 선택 사항이 nil인 경우 런타임 충돌이 발생합니다. 포장을 풀기 전에 값이 있는지 확인해야합니다.

var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.

선택 사항 확인 및 사용

포장을 풀고 옵션을 사용하기 전에 항상 nil을 확인해야하므로 다음과 같은 일반적인 패턴이 있습니다.

var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
    let unwrappedMealPreference: String = mealPreference!
    print("Meal: \(unwrappedMealPreference)") // or do something useful
}

이 패턴에서 값이 존재하는지 확인한 다음 값이 확실하면 사용하기 위해 임시 상수로 강제 랩 해제합니다. 이것이 일반적인 일이기 때문에 Swift는 "if let"을 사용하여 지름길을 제공합니다. 이것을 "선택적 바인딩"이라고합니다.

var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
    print("Meal: \(unwrappedMealPreference)") 
}

이것은 임시 상수 (또는 변수를 바꿀 경우 생성 letvar그 범위에서만 경우의 괄호 안에 참조). "unwrappedMealPreference"또는 "realMealPreference"와 같은 이름을 사용해야하는 부담이 있으므로 Swift를 사용하면 원래 변수 이름을 재사용하여 대괄호 범위 내에 임시 이름을 만들 수 있습니다.

var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // separate from the other mealPreference
}

다음은 다른 변수가 사용됨을 보여주는 코드입니다.

var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
    mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"

선택적 바인딩은 선택적이 nil인지 확인하여 작동합니다. 그렇지 않은 경우 옵션을 제공된 상수로 풀고 블록을 실행합니다. Xcode 8.3 이상 (Swift 3.1)에서 이와 같은 옵션을 인쇄하려고하면 쓸모없는 경고가 발생합니다. 옵션을 사용하여 debugDescription침묵 시키십시오.

print("\(mealPreference.debugDescription)")

옵션은 무엇입니까?

옵션에는 두 가지 사용 사례가 있습니다.

  1. 실패 할 수있는 것 (무엇을 기대했지만 아무것도 얻지 못했습니다)
  2. 지금은 아니지만 나중에있을 수있는 것들 (그리고 그 반대)

구체적인 예 :

  • 클래스 와 같이 middleName또는 클래스 spouse에 있을 수있는 속성Person
  • 배열에서 일치하는 항목을 검색하는 것과 같이 값을 반환하거나 아무것도 반환하지 않는 메서드
  • 파일의 내용을 읽으려고 시도하는 것처럼 (결과적으로 파일의 데이터를 반환하지만) 파일이 존재하지 않는 것처럼 결과를 반환하거나 오류를 가져 와서 아무것도 반환하지 않는 방법
  • 항상 설정할 필요는 없으며 일반적으로 초기화 후에 설정되는 위임 속성
  • 대한 weak클래스의 속성. 그들이 가리키는 것은 nil언제든지 설정할 수 있습니다
  • 메모리를 확보하기 위해 해제해야하는 큰 자원
  • 별도의 데이터를 사용하는 대신 값이 설정되었는지 (데이터가 아직로드되지 않은 경우> 데이터)를 알아야하는 방법이 필요한 경우 Boolean

Objective-C에는 옵션이 없지만 nil을 반환하는 동등한 개념이 있습니다. 객체를 리턴 할 수있는 메소드는 대신 nil을 리턴 할 수 있습니다. 이것은 "유효한 개체가 없음"을 의미하는 것으로 종종 무언가 잘못되었다고 말하는 데 사용됩니다. 프리미티브 또는 기본 C 유형 (열거 형, 구조체)이 아닌 Objective-C 객체에서만 작동합니다. 오브젝티브 C는 종종 이러한 값의 부재 나타내는 유형을 전문화했다 ( NSNotFound정말 NSIntegerMax, kCLLocationCoordinate2DInvalid좌표 잘못된 표현하기 위해, -1또는 부정적인 값도 사용된다). 코더는 이러한 특수 값에 대해 알아야하므로 각 경우에 대해 문서화하고 학습해야합니다. 메소드가 nil매개 변수로 사용할 수없는 경우 이를 문서화해야합니다. Objective-C에서nil모든 객체가 포인터로 정의되었지만 nil특정 (0) 주소를 가리키는 것처럼 포인터 였습니다. Swift에서 nil리터럴은 특정 유형이 없음을 의미합니다.


비교 nil

당신은 옵션을 다음과 같이 사용할 수있었습니다 Boolean:

let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}

최신 버전의 Swift에서는을 사용해야 leatherTrim != nil합니다. 왜 이런거야? 문제는 Boolean옵션으로 포장 할 수 있다는 것입니다. 당신이 Boolean이것을 좋아 한다면 :

var ambiguous: Boolean? = false

여기에는 값이없는 값과 값이있는 값의 두 종류의 "거짓"이 false있습니다. Swift는 애매 모호함을 싫어하므로 이제 선택 사항을 항상 확인해야합니다 nil.

옵션의 요점이 무엇인지 궁금 할 수 Boolean있습니까? 다른 옵션과 마찬가지로 .none상태는 값을 아직 알 수 없음을 나타낼 수 있습니다. 네트워크 호출의 다른 쪽 끝에는 폴링하는 데 약간의 시간이 걸릴 수 있습니다. 선택적 부울은 " 세 값 부울 " 이라고도합니다.


스위프트 트릭

Swift는 옵션을 사용하기 위해 몇 가지 트릭을 사용합니다. 이 세 줄의 보통처럼 보이는 선택적 코드를 고려하십시오.

var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }

이 줄들 중 어느 것도 컴파일해서는 안됩니다.

  • 첫 번째 줄은 두 가지 다른 유형 인 문자열 리터럴을 사용하여 선택적 문자열을 설정합니다. 이 String유형이 다른 경우에도
  • 두 번째 줄은 선택적인 문자열을 두 가지 다른 유형 인 nil로 설정합니다.
  • 세 번째 줄은 선택적 문자열을 두 가지 유형의 nil과 비교합니다.

이 라인이 작동하도록하는 옵션의 구현 세부 사항 중 일부를 살펴 보겠습니다.


옵션 만들기

?Swift 컴파일러가 활성화 한 구문 설탕은 선택적인 옵션을 만드는 데 사용 됩니다. 먼 길을 가고 싶다면 다음과 같이 옵션을 만들 수 있습니다.

var name: Optional<String> = Optional("Bob")

이것은 Optional첫 번째 이니셜 라이저를 호출 public init(_ some: Wrapped)하여 괄호 안에 사용 된 유형에서 선택 사항의 연관된 유형을 유추합니다.

옵션을 만들고 설정하는 더 긴 방법 :

var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")

에 옵션 설정 nil

초기 값이없는 옵션을 만들거나 초기 값이 같은 옵션을 만들 수 있습니다 nil(둘 다 동일한 결과를 가짐).

var name: String?
var name: String? = nil

nil프로토콜 ExpressibleByNilLiteral(이전의 이름 NilLiteralConvertible) 은 옵션을 동일하게 허용 합니다. 옵션은 Optional두 번째 이니셜 라이저 인으로 생성됩니다 public init(nilLiteral: ()). 문서에서는 ExpressibleByNilLiteral선택 사항을 제외하고는 코드에서 nil의 의미를 바꿀 수 있기 때문에 선택 사항을 제외하고 는 사용해서는 안된다고 말합니다 .

class Clint: ExpressibleByNilLiteral {
    var name: String?
    required init(nilLiteral: ()) {
        name = "The Man with No Name"
    }
}

let clint: Clint = nil // Would normally give an error
print("\(clint.name)")

동일한 프로토콜을 사용하여 이미 작성된 옵션을로 설정할 수 있습니다 nil. 권장하지는 않지만 nil 리터럴 이니셜 라이저를 직접 사용할 수 있습니다.

var name: Optional<String> = Optional(nilLiteral: ())

옵션과 비교 nil

선택 사항은 정의에서 볼 수있는 두 개의 특수 "=="및 "! ="연산자를 Optional정의합니다. 첫 번째 ==옵션은 선택 사항이 nil인지 확인합니다. .none으로 설정된 두 개의 다른 옵션은 연결된 유형이 동일한 경우 항상 동일합니다. nil과 비교할 때 장면 뒤에서 Swift는 동일한 연관된 ​​유형의 옵션을 작성하고 .none으로 설정 한 다음 비교에 사용합니다.

// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
    print("tuxedoRequired is nil")
}

두 번째 ==연산자를 사용하면 두 가지 옵션을 비교할 수 있습니다. 둘 다 동일한 유형이어야하고 해당 유형을 준수해야합니다 Equatable(일반 "=="연산자와 비교할 수있는 프로토콜). 스위프트 (아마도) 두 값을 풀고 직접 비교합니다. 또한 선택 사항 중 하나 또는 둘 다가 인 경우도 처리합니다 .none. nil리터럴 과 비교하는 것의 차이점에 유의하십시오 .

또한 모든 Equatable유형을 선택적 유형의 포장 과 비교할 수 있습니다 .

let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}

뒤에서 Swift는 비교하기 전에 비 선택 사항을 선택 사항으로 래핑합니다. 리터럴과도 작동합니다 ( if 23 == numberFromString {)

나는 두 개의 ==연산자 가 있다고 말 했지만 실제로 nil비교의 왼쪽 에 넣을 수있는 세 번째 연산자 가 있습니다.

if nil == name { ... }

명명 옵션

선택적 유형의 이름을 비 선택적 유형과 다르게 지정하는 스위프트 규칙은 없습니다. 사람들은 이름에 선택 사항 ( "optionalMiddleName"또는 "possibleNumberAsString")을 표시하기 위해 이름에 무언가를 추가하지 말고 선언이 선택 사항 유형임을 표시하도록하십시오. 선택 사항에서 값을 보유 할 이름을 지정하려는 경우 어려움이 있습니다. "middleName"이라는 이름은 이것이 문자열 유형임을 의미하므로 문자열 값을 추출 할 때 종종 "actualMiddleName"또는 "unwrappedMiddleName"또는 "realMiddleName"과 같은 이름으로 끝날 수 있습니다. 선택적 바인딩을 사용하고 변수 이름을 재사용하여이 문제를 해결하십시오.


공식적인 정의

에서 스위프트 프로그래밍 언어에서 "기본 사항" :

Swift는 또한 값이없는 것을 처리하는 선택적 유형을 도입했습니다. 선택 사항은 "값이 있고 x와 같습니다"또는 "값이 전혀 없습니다"라고 말합니다. 선택 사항은 Objective-C에서 포인터로 nil을 사용하는 것과 유사하지만 클래스뿐만 아니라 모든 유형에서 작동합니다. 옵션은 Objective-C의 nil 포인터보다 안전하고 표현력이 뛰어나며 Swift의 가장 강력한 기능의 핵심입니다.

선택 사항은 Swift가 유형이 안전한 언어라는 사실의 예입니다. Swift를 사용하면 코드에서 사용할 수있는 값 유형을 명확하게 파악할 수 있습니다. 코드의 일부에 문자열이 필요한 경우 형식 안전으로 인해 실수로 Int를 전달할 수 없습니다. 이를 통해 개발 프로세스에서 가능한 빨리 오류를 포착하고 수정할 수 있습니다.


마무리하기 위해 다음은 옵션에 대한 1899의시입니다.

어제 계단에
나는 없었다 사람이 만난
그는이 오늘 다시 아니었다
내가 원하는, 나는 그가 멀리 가고 싶어 할

Antigonish을


추가 자료 :


5
@KaanDedeoglu 불행히도 Steve는 매우 선택적입니다. 그는 여기 있었지만 지금은 없습니다.
nevan king

19
if myString더 이상 컴파일하지 않습니다. 당신은 필요합니다 if myString != nil. 설명서를 참조하십시오 .
Pang

5
에 대한 가장 명확한 설명? 그리고! 웹에서 찾은 Swift에서 사용하십시오. 감사합니다
mindbomb

2
mateo 는 선택 사항에 대해 깊이 있고 쉽게 설명 할 수있는 방법을 설명합니다.
iluvatar_GR

4
이 설명에 감사드립니다. Apple의 설명서보다 훨씬 명확합니다.
yesthisisjoe

16

의는의 예를 보자 NSError당신이 무기 호를 반환하는 선택하게 할 것 반환되는 오류가없는 경우. 오류가 없으면 값을 할당 할 필요가 없습니다.

var error: NSError? = nil

또한 기본값을 가질 수 있습니다. 따라서 함수에 아무것도 전달되지 않으면 메소드에 기본값을 설정할 수 있습니다

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}

"아니오 인 경우, 그 표현의 결과도 나쁘지 않다"는 문장은 단순히 잘못된 것입니다. 표현식에 선택적 값이 있어도 func isNil<T>(t: T?) -> Bool { return t == nil }반환됩니다 . truenil
true를 반환

엄청나게 나쁜 코드 샘플. 더 나은 것을 생각할 수 없습니까? 왜 간단하지 return x == 5않습니까? 5의 특별한 점은 무엇입니까?
Atomosk

아니, 2 년 전 나는 더 나은 것을 생각할 수 없었다. 오늘 예, 그러나 이것이 요점을 얻습니까? 예. @Atomosk 입력에 감사드립니다. 정말 도움이됩니다.
John Riselvato

12

nilSwift에서 가리키는 변수를 가질 수 없습니다 . 포인터와 널 포인터가 없습니다. 그러나 API에서는 종종 특정 종류의 값 또는 부족한 값을 나타낼 수 있기를 원합니다. 예를 들어, 내 창에 대리인이 있습니까? 그렇다면 누구입니까? 선택 사항은 Swift의 형식 안전, 메모리 안전 방법입니다.


11

나는 초보자로서 내 머리에 있었던 불확실성을 없애기 위해 위의 대부분을 요약 한 짧은 대답을했다.

Objective-C와 달리 Swift 에는 nil 을 포함 할 수있는 변수가 없으므로 Optional 변수 유형이 추가되었습니다 ( "?"로 접미어가있는 변수).

    var aString = nil //error

큰 차이는 선택적 변수가 바로 여기에 포함 (일반의 Obj-C 변수처럼) 값을 저장하지 않는 것이 두 가지 상태 " 값을 갖는다 "또는 " 전무가 "

    var aString: String? = "Hello, World!"
    aString = nil //correct, now it contains the state "has nil"

즉, 다른 상황에서 해당 변수를 확인할 수 있습니다.

if let myString = aString? {
     println(myString)
}
else { 
     println("It's nil") // this will print in our case
}

"!"를 사용함으로써 접미사로 묶인 경우에만 래핑 된 값에 액세스 할 수 있습니다 . (즉, nil 이 아님 ) :

let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!

println(anotherString) //it will print "Hello, World!"

그래서 "?"를 사용해야합니다. 그리고 "!" 기본적으로 모두 사용하지는 않습니다. (이것은 나의 가장 큰 당황이었다)

나는 또한 위의 답변에 동의합니다 : 선택적 유형은 부울로 사용할 수 없습니다 .


7

값이없는 객관적인 C 변수는 'nil'과 같았습니다 ( 'nil'값을 0과 false와 동일하게 사용할 수도 있음). 따라서 조건문에 변수를 사용할 수있었습니다 (값을 갖는 변수는 'TRUE와 동일합니다' '및 값이없는 값은'FALSE '와 같음).

Swift는 '선택적 값'을 제공하여 형식 안전성을 제공합니다. 즉, 다른 유형의 변수를 할당하여 생성 된 오류를 방지합니다.

따라서 Swift에서는 조건문에 부울 만 제공 할 수 있습니다.

var hw = "Hello World"

여기서조차 'hw'는 문자열이지만 목표 C와 같은 if 문에서는 사용할 수 없습니다.

//This is an error

if hw

 {..}

이를 위해서는 다음과 같이 만들어야합니다.

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}

5

선택적 값을 사용하면 값이 없음을 표시 할 수 있습니다. SQL의 NULL 또는 Objective-C의 NSNull과 약간 비슷합니다. "기본"유형에도 사용할 수 있기 때문에 이것이 개선 될 것 같습니다.

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

발췌 : Apple Inc.“Swift Programming Language.” iBooks. https://itun.es/gb/jEUH0.l


6
nil열거 형 상수에 대한 구문 설탕 일뿐입니다 OptionalValue<T>.None( T사용하는 컨텍스트에 적합한 유형 nil). ?에 대한 바로 가기입니다 OptionalValue<T>.Some(T).
rickster 2016 년

4

선택 사항은 값이 유형에 해당하는지 Swift가 완전히 확실하지 않음을 의미합니다 (예 : Int? Swift는 숫자가 Int인지 완전히 확신하지 못합니다.

이를 제거하기 위해 사용할 수있는 세 가지 방법이 있습니다.

1) 유형이 완전히 확실하면 느낌표를 사용하여 다음과 같이 강제로 줄 바꿈을 해제 할 수 있습니다.

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

옵션을 강제로 줄 바꿈 해제하고 nil과 같으면 다음과 같은 충돌 오류가 발생할 수 있습니다.

여기에 이미지 설명을 입력하십시오

이것이 반드시 안전하지는 않으므로 다음과 같은 유형과 값을 확신 할 수없는 경우 충돌을 방지 할 수있는 방법이 있습니다.

방법 2와 3은이 문제를 방지합니다.

2) 암시 적으로 래핑되지 않은 옵션

 if let unwrappedAge = age {

 // continue in here

 }

래핑되지 않은 유형은 이제 Int 가 아닌 Int입니까? .

3) 가드 진술

 guard let unwrappedAge = age else { 
   // continue in here
 }

여기서부터 래핑되지 않은 변수를 사용할 수 있습니다. 변수 유형이 확실하면 랩 해제 (!로) 만 강제 실행하십시오.

프로젝트와 함께 행운을 빕니다!


1

내가 배우기 시작했을 때 Swift왜 선택적인지 깨닫기가 매우 어려웠습니다 .

이런 식으로 생각하자. 클래스 생각해 보자 Person두 가지 특성이있다 namecompany.

class Person: NSObject {

    var name : String //Person must have a value so its no marked as optional
    var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible

    init(name:String,company:String?) {

        self.name = name
        self.companyName = company

    }
}

이제 몇 개의 객체를 만들 수 있습니다 Person

var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil

그러나 우리는 전달할 수 없습니다 Nilname

var personWithNoName:Person = Person.init(name: nil, company: nil)

이제 왜 우리가 사용하는지에 대해 이야기합시다 optional?. 우리가 추가 할 위치 상황을 고려할 수 있습니다 Inc처럼 회사 이름 뒤에 apple있을 것입니다 apple Inc. Inc회사 이름 뒤에 추가 하고 인쇄해야합니다.

print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.

이제 왜 옵션이 발생하는지 연구 해 봅시다.

if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

로 대체 할 수 bob있습니다tom

if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

그리고 축하합니다! 우리는 제대로 다루었 다optional?

실현 포인트는

  1. 가능한 경우 변수를 선택 사항으로 표시합니다 nil
  2. 코드 컴파일러에서이 변수를 사용하려면 해당 변수가 포함 된 경우 해당 변수를 올바르게 처리해야하는지 확인해야합니다 nil.

감사합니다 ... 행복한 코딩


0

아래 코드 Playground로 실험 해보십시오. 선택 사항과 사용 이유를 명확하게 알 수 있기를 바랍니다.

var sampleString: String? ///Optional, Possible to be nil

sampleString = nil ////perfactly valid as its optional

sampleString = "some value"  //Will hold the value

if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.

    print(value+value)  ////Sample String merged into Two
}

sampleString = nil // value is nil and the

if let value = sampleString{

    print(value + value)  ///Will Not execute and safe for nil checking
}

//   print(sampleString! + sampleString!)  //this line Will crash as + operator can not add nil

0

에서 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :

선택적 체인은 현재 0 일 수있는 옵션에 대한 속성, 메서드 및 아래 첨자를 쿼리하고 호출하는 프로세스입니다. 선택 사항에 값이 있으면 특성, 메소드 또는 첨자 호출이 성공합니다. 선택 사항이 nil이면 속성, 메서드 또는 아래 첨자 호출은 nil을 반환합니다. 여러 쿼리를 함께 연결할 수 있으며 체인의 링크가없는 경우 전체 체인이 정상적으로 실패합니다.

더 깊이 이해하려면 위의 링크를 읽으십시오.


0

잘...

? (선택 사항) 변수에 nil 값이 포함될 수 있음을 나타냅니다 ! (unwrapper) 는 변수가 런타임에 사용될 때 (값을 얻으려고 할 때) 메모리 (또는 값)가 있어야 함을 나타냅니다.

가장 큰 차이점은 옵션이 nil 인 경우 선택적 chaining이 정상적으로 실패하는 반면, 옵션이 nil 인 경우 강제 언 래핑이 런타임 오류를 트리거한다는 것입니다.

선택적 체인이 nil 값에서 호출 될 수 있다는 사실을 반영하기 위해 쿼리하는 속성, 메서드 또는 아래 첨자가 선택적이 아닌 값을 반환하더라도 선택적 체인 호출의 결과는 항상 선택적 값입니다. 이 선택적 리턴 값을 사용하여 선택적 체인 호출이 성공했는지 (반환 된 선택적에 값이 포함되어 있는지) 또는 체인의 nil 값으로 인해 성공하지 못한 지 (반환 된 선택적 값은 nil) 여부를 확인할 수 있습니다.

특히 선택적 체인 호출의 결과는 예상 반환 값과 동일한 유형이지만 옵션으로 래핑됩니다. 일반적으로 Int를 반환하는 속성은 Int? 옵션 체인을 통해 액세스 할 때.

var defaultNil : Int?  // declared variable with default nil value
println(defaultNil) >> nil  

var canBeNil : Int? = 4
println(canBeNil) >> optional(4)

canBeNil = nil
println(canBeNil) >> nil

println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper

var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4

var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error

다음은 Apple 개발자위원회의 선택적 튜토리얼입니다 : 옵션 체인



-1

다음은 Swift에서 동등한 선택적 선언입니다.

var middleName: String?

이 선언은 String 유형의 middleName이라는 변수를 만듭니다. String 변수 유형 뒤의 물음표 (?)는 middleName 변수가 String 또는 nil 일 수있는 값을 포함 할 수 있음을 나타냅니다. 이 코드를 보는 사람은 middleName이 nil 일 수 있음을 즉시 알고 있습니다. 자체 문서화입니다!

선택적 상수 또는 변수에 대한 초기 값을 지정하지 않으면 (위 그림 참조) 값이 자동으로 nil로 설정됩니다. 원하는 경우 초기 값을 nil로 명시 적으로 설정할 수 있습니다.

var middleName: String? = nil

링크 아래 옵션 읽기에 대한 자세한 내용

http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values


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