[TIL] 10.04

Junyoung_Hong·2023년 10월 4일
0

TIL_10월

목록 보기
2/20
post-thumbnail

1. Optional

Optional이란 있을 수도, 없을 수도(nil) 있는 것 이다. 다른 언어를 공부하면 NULL을 볼 수 있다. 다른 언어에서는 NullPointException 오류가 발생하면 프로그램이 멈춘다. 스위프트는 안정성이 특징인데, Optional이 안정성을 제공하는 기능이다. 왜냐하면 값이 nil이어도 프로그램이 진행되기 때문이다.

옵셔널은 상자를 생각하면 쉽다. 단순하게 nil을 할당할 수 있는 변수라고 생각하기 보다는 nil까지 담을 수 있는 상자라고 생각하면 이해가 쉬울것이다.

1-1. Optional 선언

변수되에 ? 를 붙여서 선언할 수 있다.

var job: String = "개발자"
print(job)

실행결과는 "개발자"라는 문자열이다.

var job: String
print(job)

그런데 타입만 정해주고, 값은 정해주지 않은 상태로 출력을 하게되면 오류가 생길것이다.

var job: String?
print(job)

이 때, ? 를 붙여서 옵셔널로 만들고 출력을 하게 되면 nil이 출력된다. 옵셔널 변수는 값을 가지지 않더라도 오류가 발생하지 않고, nil 값을 가지게 되는 것이다.

var job: String? = "개발자"
print(job)

옵셔널 변수에 값을 넣은 후에 출력을 하게 되면 Optional("개발자") 라고 출력이 된다.

  • 옵셔널 변수에 값이 할당 O : 할당된 값을 가짐
  • 옵셔널 변수에 값이 할당 X : nil 값을 가짐

1-2. Optional Unwrapping(옵셔널 추출)

옵셔널로 만든 변수에 값을 할당하더라도, 그 결과는 Optional()을 포함한 상태였다. 이제 상자, 즉 Optional()을 꺼내는 과정이다.

1-2-1. Forced Unwrapping(강제 추출)

가장 직접적이고 직관적인 방법이다. 변수명 뒤에 ! 를 붙이는 것이다.

var job: String? = "개발자"
print(job!)

이렇게 되면 "개발자"만 출력이 된다. 그렇지만 변수에 값이 할당이 되었는지 확인을 하지 않고, 강제로 언래핑하기 때문에 굉장히 위험한 방식이다.

var job: String?
print(job!)

이렇게 실행을 시키면 Execution was interrupted, reason: EXC_BREAKPOINT 오류가 발생한다.

Expression implicitly coerced from ‘String?’ to ‘Any’ 이런 경고도 볼 수 있는데, nil coalescing을 사용하면 된다.

Nil coalescing은 변수의 값이 nil일 경우에 값을 지정해주는 것을 의미한다. 사용은 변수명 ?? 값 이렇게 하면 되고, 변수의 값이 nil일 경우 을 할당한다는 의미이다.

var job: String?
print(job ?? "없음")

출력결과는 "없음"이다.

1-2-2. Optional Binding(옵셔널 바인딩)

옵셔널 바인딩은 좀 더 안전한 방식으로 nil인지 먼저 확인하고 추출하는 방식이다.

if let 을 이용하는 경우

var job: String? = "개발자"

func printJob(job: String?) {
    if let jobName = job {
        print(jobName)
    } else {
        print("없음")
    }
}

printJob(job: job)	// "개발자"

job이라는 변수가 값을 가지고 있다면 jobName이라는 새로운 변수에 값을 할당한 후, true를 반환하여 해당 코드가 실행된다. 값이 없다면 false를 반환하여 else 코드가 실행된다. 핵심 코드인 if let jobName = job 의 의미는 만약 옵셔널이 아닌 jobName 변수에 옵셔널인 job 값을 할당 할 수 있으면 이라고 생각하면 쉽다.

guard let을 이용하는 경우
guard let 은 함수에서만 쓰일 수 있기 때문에 함수로 만들어야 한다.

var job: String? = "개발자"

func printJob(job: String?) {
    guard let jobName = job else {
    	print("없음")
        return
    }
    print(jobName)
}

printJob(job: job)	// "개발자"

job이 값을 가지고 있는지 확인 후, 값이 없다면 else 에 해당하는 코드를 실행하고 그 값을 반환하여 guard 에서 나온다. job이 값을 가지고 있다면 else 를 지나쳐 print(jobName) 을 실행한다.

두가지 방식의 차이는 다음과 같다.

  • if let: 값의 유무를 확인 후, 있을 때 없을 때 각각의 코드를 실행
  • guard let: 값의 유무를 확인 후, 값이 없으면 함수를 실행하지 못하도록 방어
  • 복잡도: if let > guard let

1-2-3. Optional Chaining(옵셔널 체이닝)

옵셔널을 반복사용하여 옵셔널이 체인처럼 꼬리에 꼬리를 물고 있는 모양이다. 체인처럼 서로가 이어져있기 때문에 중간에 하나라도 값이 존재하지 않으면 (nil이면) 바로 nil을 반환한다.

옵셔널 체이닝은 다음과 같은 문법으로 표현된다.

optionalValue?.property
optionalValue?.method()

여기서 optionalValue는 옵셔널 값이고, property는 속성 이름, method()는 메서드 호출이다. 옵셔널 체이닝 연산자 ?는 옵셔널 값이 nil이 아닌 경우에만 속성에 접근하거나 메서드를 호출하라는 의미이다. 만약 옵셔널 값이 nil인 경우, 체이닝된 표현식은 자동으로 nil을 반환한다.

class Person {
    var name: String
    var address: Address?
    
    init(name: String) {
        self.name = name
    }
    
    func printAddress() {
        if let city = address?.city {
            print("City: \(city)")
        } else {
            print("No address available")
        }
    }
}

class Address {
    var city: String
    
    init(city: String) {
        self.city = city
    }
}

let person = Person(name: "Bob")
person.printAddress() // 출력: "No address available"

person.address = Address(city: "New York")
person.printAddress() // 출력: "City: New York"

printAddress 메서드는 옵셔널 체이닝을 사용하여 address의 city 속성에 접근하고 출력한다. person 객체가 주소 정보를 가지고 있을 때에만 "City" 값을 출력하고, 그렇지 않은 경우에는 "No address available"을 출력한다.

let numbers: [Int]? = [1, 2, 3, 4, 5]

let firstNumber = numbers?[0] // numbers가 nil이 아니면 첫 번째 요소에 접근
let fifthNumber = numbers?[4] // numbers가 nil이 아니면 다섯 번째 요소에 접근

print(firstNumber) // 출력: Optional(1)
print(fifthNumber) // 출력: Optional(5)

배열 numbers가 옵셔널이며 옵셔널 체이닝을 사용하여 배열의 요소에 접근하는 예시이다. 배열이 nil이 아닌 경우에만 요소에 접근하고 값을 반환한다.

2. null VS nil

2-1. null

  • null은 주로 C와 C++와 같은 언어에서 사용되는 용어이다.
  • null은 포인터나 참조 타입 변수가 가리키는 값이 없음을 나타낸다. 즉, null은 메모리 주소가 0 또는 비어있음을 나타낸다.
  • null은 주로 메모리 관리와 관련이 있으며, 포인터를 초기화하거나 메모리를 해제할 때 사용된다.

2-2. nil

  • nil은 Objective-C, Swift 및 다른 Apple 관련 프로그래밍 언어에서 사용되는 용어이다.
  • nil은 객체 지향 언어에서 사용되며, 객체 또는 클래스 인스턴스 변수가 초기화되지 않거나 아무런 값을 가지고 있지 않음을 나타낸다.
  • nil은 주로 클래스 인스턴스나 객체와 관련이 있으며, 메모리 관리 및 안전성을 위해 사용된다. Swift에서는 옵셔널 타입을 통해 nil 값을 다루고 안전하게 처리할 수 있다.
  • Objective-C와 Swift에서의 의미도 다르다. Objective-C에서 nil은 존재하지 않는 object를 가리키는 pointer이다. Swift에서 nil은 pointer가 아닌, 특정 타입의 value가 없음을 나타낸다.
profile
iOS 개발자를 향해 성장 중

0개의 댓글