[Swift 프로그래밍] 옵셔널 체이닝 (Optional Chaining)

이정훈·2022년 6월 14일
0

Swift 기본

목록 보기
13/22
post-thumbnail

본 내용은 스위프트 프로그래밍 3판 (야곰 지음) 교재를 공부한 내용을 바탕으로 작성 하였습니다.

옵셔널 체이닝(Optional Chaining)이란?


옵셔널 체이닝의 정의는 다음과 같다.

nil일지 모르는 프로퍼티, 메서드, 서브 스크립트 등을 가져오거나 호출 할 때 사용되는 과정

대체로 구조체 안에 있는 인스턴스 혹은 클래스 안에 있는 인스턴스와 같이 중첩된 형태에서의 프로퍼티, 메서드 서브 스크립트 등에 졉근할때 사용한다.
당연하게도 옵셔널에 값이 있으면 값을 호출 할 수 있고, 값이 없다면 nil을 반환한다.

옵셔널 체이닝은 기본적으로 옵셔널로 선언된 변수나 상수에 접근 하므로 접근 하고자하는 변수나 상수(프로퍼티)에 물음표 (?)를 사용하여 표현한다.

다음은 옵셔널 체이닝을 사용하기 위한 틀을 구성한 것이다.

class Major {                       //전공
    var field: String               //전공 분야
    
    init(field: String) {
        self.field = field
    }
}

struct University {                 //학교
    var name: String                //학교 이름
    var location: String            //학교 위치
    var major: Major?               //전공 관련 정보
    var summary: String?            //학교 소개
}

class Student {                     //학생
    var grade: String               //학년
    var university: University?     //학교 관련 정보
    
    init(grade: String) {
        self.grade = grade
    }
}

class Person {                      //사람
    var name: String                //이름
    var student: Student?           //학생 관련 정보
    
    init(name: String) {
        self.name = name
    }
}

각 클래스와 구조체 내부에는 클래스와 구조체 타입으로 선언된 변수(프로퍼티)들이 있으며 이러한 변수들은 모두 옵셔널 형태로 선언되어 있다.

옵셔널 체이닝 구현


이제 Person 클래스로 사람 인스턴스를 생성하고 Major 클래스의 field 프로퍼티에 접근하는 코드를 살펴보자

먼저 옵셔널 바인딩을 사용한 예시이다.

//옵셔널 바인딩을 이용한 프로퍼티 접근
let personLee: Person = Person(name: "이철수")

var yourField: String? = nil

if let personStudent: Student = personLee.student {     //옵셔널 바인딩으로 nil이 아닌지 판별
    if let personUniversity: University = personStudent.university {
        if let personMajor: Major = personUniversity.major {
            yourField = personMajor.field
        }
    }
}

if let field: String = yourField {
    print(field)
} else {
    print("전공에 대한 정보가 없습니다.")
}

옵셔널 바인딩을 사용한 경우 각 프로퍼티에 접근 할 때마다 프로퍼티에 값이 있는지 확인하는 작업을 거친다.

옵셔널 체이닝을 이용한 경우 매우 간단하게 표현 할 수 있으며 예시는 다음과 같다.

//옵셔널 체이닝을 이용한 프로퍼티 접근
let personLee: Person = Person(name: "이철수")

var yourField: String? = nil

if let yourFiled: String = personLee.student?.university?.major?.field {
    print(yourFiled)
} else {
    print("전공에 대한 정보가 없습니다.")
}

옵셔널 체이닝을 이용한 방식에서 personLee 인스턴스는 student 프로퍼티에 값의 존재 유무를 판별한다. 값이 존재한다면 다음 university 프로퍼티로 넘어가서 값의 존재를 판별하고 student 프로퍼티에 값이 없다면 nil을 반환하여 else문으로 넘어가는 과정을 반복한다.

다만 위의 코드는 아직 프로퍼티에 값을 할당해 주지 않았기 때문에 모두 else문이 호출 될 것이다.

옵셔널 체이닝을 이용한 값 할당


이제 프로퍼티에 값을 할당해 보자

프로퍼티에 값을 할당해 주기 위해서 클래스와 구조체 타입으로 선언된 프로퍼티에는 인스턴스를 생성하여 대입한다. 그리고 우리가 원하는 프로퍼티인 field 프로퍼티에는 직접 String 타입의 문자열을 대입하고, field 프로퍼티에 접근하기 위하여 상위 프로퍼티 부터 하나씩 값을 할당해 준다.

//옵셔널 체이닝을 이용한 값 할당
personLee.student = Student(grade: "sophomore")
personLee.student?.university = University(name: "한국대학교", location: "대한민국")
personLee.student?.university?.major = Major(field: "nil")
personLee.student?.university?.major?.field = "컴퓨터공학"

print(personLee.student?.university?.major?.field)

옵셔널 체이닝을 사용한 메서드 호출


옵셔널 체이닝을 사용하여 메서드를 호출 하는 방법은 프로퍼티에 접근하는 방법과 비슷하다.

먼저 University구조체 내부에 호출할 메서드를 먼저 선언 한다.

struct University {                 //학교
    var name: String                //학교 이름
    var location: String            //학교 위치
    var major: Major?               //전공 관련 정보
    var detailInfo: String?            //학교 소개
    
    init(name: String, location: String) {
        self.name = name
        self.location = location
    }
    
    //메서드
    func introduce() -> String? {
        var yourInfo: String? = nil  //전공에 관련된 정보 저장하는 변수
        
        if let majorInfo: Major = self.major {
            yourInfo = majorInfo.field
        } else {
            if let detail = self.detailInfo {
                yourInfo = detail
            }
        }
        
        if let info: String = yourInfo {
            var introduce: String = self.location + "에 위치한 "
            
            introduce += self.name + "에서 "
            introduce += info + " 전공을 공부하고 있습니다."
            
            return introduce
        } else {
            return nil
        }
    }
    
    func printInfo() {
        if let introduction = self.introduce() {
            print(introduction)
        }
    }
}

이전 옵셔널 체이닝을 이용한 값 할당에서 University 구조체의 생성자를 통해 내부 프로퍼티값을 할당 하였기 때문에 정상적으로 원하는 값을 반환 할 수 있을것이다. 만약 구조체 내부 프로퍼티에 값이 할당 되어있지 않다면 nil을 반환 하도록 하였다.

다음은 선언한 메서드를 옵셔널 체이닝으로 호출하는 코드이다.

//옵셔널 체이닝을 이용한 메서드 호출
personLee.student?.university?.introduce()?.isEmpty     //false
personLee.student?.university?.printInfo()  //대한민국에 위치한 한국대학교에서 컴퓨터공학 전공을 공부하고 있습니다.

먼저 introduce 메서드를 호출 하였을때 값이 존재하는지 유무를 확인해 보았다. 내부 프로퍼티 값을 할당해 주었기에 정상적으로 값을 반환하는 것을 볼 수 있다.

profile
새롭게 알게된 것을 기록하는 공간

0개의 댓글