ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • swift - Optional Chaining
    swift 2021. 1. 4. 20:28

    Optional Chaining

    struct Contacts {
       var email: [String: String]
       var address: String
    }
    
    struct Person {
       var name: String
       var contacts: Contacts
    
       init(name: String, email: String) {
          self.name = name
          contacts = Contacts(email: ["home": email], address: "Seoul")
       }
    }
    
    // 두가지만 기억하자
    
    // 1. Optional Chanining의 결과는 항상 Optional이다
    // 2. Optional Chanining에서 포함된 표현식 중에서 하나라도 nil을 리턴한다면 뒤의 표현식을 평가하지 않고 nil을 리턴한다.
    
    var p = Person(name: "James", email: "swift@example.com")
    let a = p.contacts.address
    
    var optionalP: Person? = Person(name: "James", email: "swift@example.com")
    
    // optionalP에 nil이 포함되어 있다면 그냥 nil을 리턴 아니면 쭈욱 가고
    let b = optionalP?.contacts.address
    
    optionalP = nil
    
    let c = optionalP?.contacts.address

    자 여기서 a, b, c의 데이터 타입이 Optional인지 아닌지 확인해보면

     

    a는 Optional이 아니고 b와 c는 Optional이다.

     

    왜? a는 당연히 Optional Chaining으로 접근한게 아니기 때문에 non-Optional 형태의 자료형이고

     

    b와 c는 Optional Chaining으로 접근했기 때문에

     

    더 자세히 보면 b와 c는 값을 할당하는 표현식에서 Optional 표현식 (optionalP?) 가 있기 때문에!

     

     

     

     

    표현식 중에 하나라도 Optinal 표현식이 포함되어 있다면 최종 데이터 타입은 Optional이 된다.

     

     

     

    nil이 리턴된다면 3번째 표현식 까지만 평가한다.

     


    contacts의 자료형을 Optional로 바꾸면

     

    관련된 표현식에 ! 나 ?를 붙여줘야하는데 !는 위험하니까 ?를 붙인다.

    struct Contacts {
       var email: [String: String]
       var address: String
    }
    
    struct Person {
       var name: String
       var contacts: Contacts?
    
       init(name: String, email: String) {
          self.name = name
          contacts = Contacts(email: ["home": email], address: "Seoul")
       }
    }
    
    var p = Person(name: "James", email: "swift@example.com")
    let a = p.contacts?.address
    
    var optionalP: Person? = Person(name: "James", email: "swift@example.com")
    
    // optionalP에 nil이 포함되어 있다면 그냥 nil을 리턴 아니면 쭈욱 가고
    let b = optionalP?.contacts?.address
    
    optionalP = nil
    
    let c = optionalP?.contacts?.address

     

    다시 데이터형을 보면 표현식에 Optional 다 들어가 있기 때문에 모두 Optional 자료형이 된다.

     


    괄호 전, 후에 ?를 붙이는 경우

    struct Person {
       var name: String
       var contacts: Contacts?
    
       init(name: String, email: String) {
          self.name = name
          contacts = Contacts(email: ["home": email], address: "Seoul")
       }
        
        func getContact() -> Contacts? {
            return contacts
        }
    }
    var p = Person(name: "James", email: "swift@example.com")
    p.getContact()?.address
    
    
    
    
    let f: (() -> Contacts?)? = p.getContact
    
    f?()?.address

    함수나 메소드가 리턴하는 메소드 값에 접근할 때는 괄호 뒤에 ?를 붙인다 정도만 일단 기억해두자

     


    기타 옵셔널 체이닝 속성

    struct Contacts {
       var email: [String: String]?
       var address: String
        
        func printAddress() {
            return print(address ?? "no address")
        }
    }
    
    struct Person {
       var name: String
       var contacts: Contacts?
    
       init(name: String, email: String) {
          self.name = name
          contacts = Contacts(email: ["home": email], address: "Seoul")
       }
        
        func getContact() -> Contacts? {
            return contacts
        }
    }
    
    
    
    
    // 두가지만 기억하자
    
    // 1. Optional Chanining의 결과는 항상 Optional이다
    // 2. Optional Chanining에서 포함된 표현식 중에서 하나라도 nil을 리턴한다면 뒤의 표현식을 평가하지 않고 nil을 리턴한다.
    
    var p = Person(name: "James", email: "swift@example.com")
    let a = p.contacts?.address
    
    var optionalP: Person? = Person(name: "James", email: "swift@example.com")
    
    // optionalP에 nil이 포함되어 있다면 그냥 nil을 리턴 아니면 쭈욱 가고
    let b = optionalP?.contacts?.address
    
    optionalP = nil
    
    let c = optionalP?.contacts?.address
    
    
    p.getContact()?.address
    
    let f: (() -> Contacts?)? = p.getContact
    
    f?()?.address
    
    
    // ()? -> Optional void 값을 리턴하지 않는다는 키워드
    let d = p.getContact()?.printAddress()
    
    // 이러한 구조를 알면 실제로 메소드가 호출되었는지 확인 가능
    if p.getContact()?.printAddress() != nil {
        // nil이 아니고 ()?가 호출되면 여기가 호출됨
    }
    
    if let _ = p.getContact()?.printAddress() {
        // 어차피 성공하면 ()?이 반환되기 때문에 wildcard 로 선언
    }
    
    let e = p.contacts?.email?["home"]
    
    // dictionary가 옵셔널로 선언되어 있으면 [] 앞에 ? 선언
    // 서브 스크립트접근할때는 [] 뒤에 ? 선언
    p.contacts?.email?["home"]?.count
    
    p.contacts?.address = "Daegu"
    p.contacts?.address
    
    optionalP?.contacts?.address = "Daegu"
    optionalP?.contacts?.address

    이정도로 정리하고 나중에 한번 더보자

    'swift' 카테고리의 다른 글

    swift - Functions  (0) 2021.01.04
    swift - Optional Pattern  (0) 2021.01.04
    swift - Nil-Coalescing Operator  (0) 2021.01.04
    swift - IUO(Implicitly Unwrapping Optionals )  (0) 2021.01.04
    swift - Optional Binding  (0) 2021.01.04

    댓글

Designed by Tistory.