선택적 변수 인쇄


118

이 코드 줄로 시도하고 있습니다.

class Student {
    var name: String
    var age: Int?

    init(name: String) {
        self.name = name
    }

    func description() -> String {
        return age != nil ? "\(name) is \(age) years old." : "\(name) hides his age."
    }
}

var me = Student(name: "Daniel")
println(me.description())
me.age = 18
println(me.description())

위의 코드는 다음과 같이 생성합니다.

Daniel hides his age.
Daniel is Optional(18) years old.

내 질문은 왜 옵션 (18)이 거기에 있고 옵션을 제거하고 인쇄 만 할 수 있습니까?

Daniel is 18 years old.

답변:


190

옵션이 실제로 무엇인지 이해해야합니다. 많은 Swift 초보자 var age: Int?는 나이가 가치가있을 수도 있고 없을 수도있는 Int 라고 생각 합니다. 그러나 나이는 Int를 가질 수도 있고 가지지 않을 수도있는 Optional이라는 것을 의미합니다.

description()함수 내 에서 Int를 인쇄하지 않고 대신 Optional을 인쇄합니다. Int를 인쇄하려면 Optional을 풀어야합니다. "옵션 바인딩"을 사용하여 옵션을 풀 수 있습니다.

if let a = age {
 // a is an Int
}

옵션에 개체가 있다고 확신하는 경우 "강제 래핑 해제"를 사용할 수 있습니다.

let a = age!

또는 귀하의 예에서 설명 함수에 nil에 대한 테스트가 이미 있으므로 다음과 같이 변경할 수 있습니다.

func description() -> String {
    return age != nil ? "\(name) is \(age!) years old." : "\(name) hides his age."
}

사용하도록 변경하면 예제가 약간 더 나을 것이라고 생각합니다if let age = age { return ""} else { return "" }
— kubi

13
: +1Many Swift beginners think var age: Int? means that age is an Int which may or may not have a value. But it means that age is an Optional which may or may not hold an Int.
— 리

18

선택 사항은 값이 유형에 해당하는지 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
반환 나이 사용! = nil? "(이름)은 (나이!) 살입니다." : "(이름)은 나이를 숨 깁니다."
— leedream

1
내가 가진 문제로 두통을 구했습니다. 충분히 감사 할 수 없습니다.
— Bruno Recillas

8

테스트 / 디버깅을 위해 항상 nil값 을 테스트 할 필요없이 선택 사항을 문자열로 출력하고 싶기 때문에 사용자 지정 연산자를 만들었습니다.

나는 다른 질문에서이 대답을 읽은 후에 일을 더욱 개선했습니다 .

fileprivate protocol _Optional {
    func unwrappedString() -> String
}

extension Optional: _Optional {
    fileprivate func unwrappedString() -> String {
        switch self {
        case .some(let wrapped as _Optional): return wrapped.unwrappedString()
        case .some(let wrapped): return String(describing: wrapped)
        case .none: return String(describing: self)
        }
    }
}

postfix operator ~? { }
public postfix func ~? <X> (x: X?) -> String {
    return x.unwrappedString
}

분명히 연산자 (및 그 속성)는 원하는대로 조정할 수 있거나 대신 함수로 만들 수 있습니다. 어쨌든 다음과 같은 간단한 코드를 작성할 수 있습니다.

var d: Double? = 12.34
print(d)     // Optional(12.34)
print(d~?)   // 12.34
d = nil
print(d~?)   // nil

다른 사람의 프로토콜 아이디어를 통합하면 옵션 체인을 사용할 때 종종 발생하는 중첩 된 옵션에서도 작동합니다. 예를 들면 :

let i: Int??? = 5
print(i)              // Optional(Optional(Optional(5)))
print("i: \(i~?)")    // i: 5

1
Swift 3부터는 Swift 표준 라이브러리 함수 debugPrint (_ : separator : terminator :)를 사용할 수도 있습니다. 그러나 이것은 큰 따옴표로 문자열을 인쇄합니다.
— psmythirl

@psmythirl : 알아 두세요! 그러나 때로는 선택 사항을 String다른 곳 (예 : 로그 / 오류 메시지) 으로 전달하거나 포함 할 수 있습니다 .
— Jeremy

(문자판으로 D)으로 인쇄
— DawnSong

7

최신 정보

간단히 me.age ?? "Unknown age!". 3.0.2에서 작동합니다.

이전 답변

강제 언 래핑없이 (무시 마하 시그널 / 크래시 없음)이를 수행하는 또 다른 좋은 방법은 다음과 같습니다.

(result["ip"] ?? "unavailable").description.

result["ip"] ?? "unavailable" 작업도 있어야하지만 그렇지 않습니다. 적어도 2.2에서는

물론 "사용할 수 없음"을 적합한 것으로 바꾸십시오 : "없음", "찾을 수 없음"등


4

age!대신 선택적 사용을 풀려면 age. 현재 당신은 nil. 그래서 Optional.


4

신속하게 어떤 경우 에는 그럴 Optional수 있습니다 nil. a variable가 항상 어떤 값을 가질 것이라고 100 % 확신 하고 변수를 강제로 풀기 위해 niladd !를 반환하지 않을 것입니다.

다른 경우에는 값이 확실하지 않은 경우 if let블록 을 추가 하거나 guard값이 있는지 확인하십시오. 그렇지 않으면 충돌이 발생할 수 있습니다.

대한 if let블록 :

if let abc = any_variable {
 // do anything you want with 'abc' variable no need to force unwrap now.
}

대한 guard문 :

guard 조건이 충족되지 않으면 제어를 반환하는 조건부 구조입니다.

특정 값이 존재하지 않는 경우 를 반환 할 수 있으므로 많은 상황에서 guardover if letblock 을 사용하는 것을 선호 function합니다. 변수가 존재하기 위해 정수인 함수가있을 때와 같이 가드 문에서 확인할 수 있고 반환이 존재하지 않습니다. 즉;

guard let abc = any_variable else { return }

변수가 존재하면 가드 범위 밖의 함수에서 'abc'를 사용할 수 있습니다.


3

age은 선택적 유형입니다. Optional<Int>따라서 nil과 비교하면 값이 있거나없는 경우 매번 false를 반환합니다. 값을 얻으려면 선택 사항을 풀어야합니다.

귀하의 예에서는 값이 포함되어 있는지 알지 못하므로 대신 사용할 수 있습니다.

if let myAge = age {
    // there is a value and it's currently undraped and is stored in a constant
}
else {
   // no value
}

3

다른 뷰 컨트롤러에서 문자열 (속성) 값을 인쇄하기 위해 이렇게했습니다.

ViewController.swift

var testString:NSString = "I am iOS Developer"

SecondViewController.swift

var obj:ViewController? = ViewController(nibName: "ViewController", bundle: nil)
print("The Value of String is \(obj!.testString)")

결과 :

The Value of String is I am iOS Developer

2
선택 사항을 강제로 풀지 말아야합니다
— E-

3

guard성명을 확인하십시오 .

for student in class {
    guard let age = student.age else { 
        continue 
     }
    // do something with age
}

3

기본값이있는 경우 :

print("\(name) is \(age ?? 0) years old")

또는 이름이 선택 사항 인 경우 :

print("\(name ?? "unknown") is \(age) years old")


1

내 tableview 셀에서 Optional ( "String")을 얻었습니다.

첫 번째 대답은 훌륭합니다. 그리고 그것을 알아내는 데 도움이되었습니다. 저 같은 신인들을 돕기 위해 제가 한 일입니다.

사용자 지정 개체에 배열을 만들고 있기 때문에 항상 첫 번째 위치에 항목이 있다는 것을 알고 있으므로 다른 변수에 강제로 풀 수 있습니다. 그런 다음 해당 변수를 사용하여 인쇄하거나 제 경우에는 tableview 셀 텍스트로 설정하십시오.

let description = workout.listOfStrings.first!
cell.textLabel?.text = description

지금은 너무 단순 해 보이지만 알아내는 데 시간이 걸렸습니다.


-1

이것은이 질문에 대한 정확한 답은 아니지만 이런 종류의 문제에 대한 한 가지 이유입니다. 제 경우에는 "if let"및 "guard let"을 사용하여 문자열에서 Optional을 제거 할 수 없습니다.

그래서 사용 AnyObject를 대신 모든 빠른 문자열에서 선택적 제거 할 수 있습니다.

답변은 링크를 참조하십시오.

https://stackoverflow.com/a/51356716/8334818

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