선택적 변수 인쇄


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.