iOS프로그래밍기초(Smile Han)/문법 정리

[Swift] 문법 정리 - optional, as, nil, Any, AnyObject

wse46 2024. 9. 15. 14:33
https://youtu.be/R8OWOgCNt4M?si=bldau6gYEZ3seGj2

위 영상을 보고 정리한 글입니다 (6:48 ~ 11:40)
 
 
 
# 옵셔널 타입 (optional type)

  • 옵셔널 데이터 타입은 다른 프로그래밍 언어에는 없는 새로운 개념
  • 값을 반환할 때 오류가 발생할 가능성이 있는 값 옵셔널 타입이라는 객체로 감싸서 반환함
    print(Int("100"))
      // 문자열 "100"을 정수로 변환하고자 함.
      // 변환이 성공하면, 100이 아닌 Optional(100)을 반환 : Int형 initializer
    Int("Hi")
      // 문자열 "Hi"를 정수로 변환이 불가함.
      // 변환이 실패하고 nil을 반환

    Swift에서 기본 자료형(Int, Double, String 등)은 nil 값을 저장할 수 없음
    nil도 저장하려면 옵셔널 타입으로 선언해야 함
  • 옵셔널 타입은 변수 또는 상수에 아무런 값이 할당되지 않는 상황을 안전하게 처리하기 위한 방법 제공
  • 옵셔널 타입 변수를 선언하기 위해서는 타입 선언부 뒤에 "?" 문자를 씀
    주의 : 변수명 뒤에 "?" 하는 것 아님
  • index라는 이름의 옵셔널 int 변수를 선언
    var index: Int? // index 변수는 정수 값을 갖거나 아무 값도 갖지 않을 수 있음(nil)

 
1. 강제 언래핑 (forced unwrapping)

  • 옵셔널 변수에 값이 있으면 옵셔널로 "래핑되었다(wrapped)"고 함
  • 옵셔널에 래핑된 값은 !를 사용하여 강제 언래핑(forced unwrapping)
var x : Int? // 옵셔널 정수형 변수 x 선언
x = 10 // 주석처리 하면?
print(x) // Optional(10)
print(x!) // forced unwrapping해서 10이 나옴
  • ?는 자료형 뒤
  • !는 변수명 뒤
var x : Int?
x = 10
if x != nill { // if x!=nill 이라고 쓰면 안됨
	print(x!)
}
else {
	print("nil")
}
var x1 : Int?
if x1 != nil {
	print(x1!)
}
else {
	print("nil")
}

 
 
2. 옵셔널 바인딩 (optional binding)
강제 언래핑하는 또 다른 방법으로, 옵셔널에 할당된 값을 임시 변수 또는 상수에 할당

if let constantname = optionalName {
  // 옵셔널 변수가 값이 있다면 언해핑해서 일반 상수 constantname에 대입하고 if문 실행
  // 값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}

if var variablename = optionalName {
  // 옵셔널 변수가 값이 있다면 언래핑해서 일반 변수 variablename에 대입하고 if문 실행
  // 값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
var x : Int? // x라는 옵셔널 정수 변수 선언, 초기값은 nil
x = 10 // x에 10이라는 값 할당 : optional(10)
if let xx = x { // if let 구문으로 x의 값을 안전하게 언래핑
	print(xx) // x에 값이 존재하므로, xx에 10이 할당되어 출력
}
else {
	print("nil")
}
var x1 : Int? // x1이라는 옵셔널 정수 변수 선언, 초기값은 nil
if let xx = x1 { // if let 구문으로 x1의 값을 언래핑
	print(xx)
}
else { // x1은 nil이므로, else 블록 실행
	print("nil") // "nil" 출력
}

 
여러 옵셔널 변수를 한번에 언래핑하는 방법 : 콤마 사용

var pet1 : String?
var pet2 : String?
pet1 = "cat"
pet = "dog"
if let firstPet = pet1, let secondPet = pet2 {
	print(firstPet, secondPet)
} else {
	print("nil")
}

 
 
# nil
옵셔널 변수에 nil을 할당하면 값이 없는 상태가 됨
상수나 변수가 값이 없는 상태가 존재한다면 옵셔널 타입으로 선언해야 함
 


 
# 형 변환
 
1. as로 upcasting

  • 상속 관계가 있는 클래스들끼리만 타입 캐스팅 가능
  • 자식을 부모로 캐스팅하는 것은 문제가 없음
    (자식이 부모로부터 상속받아 더 많은 것을 가지고 있기 때문)
  • as 연산자를 이용한 타입 변환 (type casting)
  • 자식 인스턴스 as 부모 클래스 // upcasting 안전한 캐스팅. 자식이 추상화됨
    형 변환은 성공할 것이기 때문에 보장된 변환 (guaranted conversion)
    UIButton은 UIControl의 자식 클래스이므로 안전하게 형 변환
    let myButton: UIButton = UIButton()
    let myControl = myButton as UIControl // 자식인스턴스 as 부모클래스
    자식 인스턴스인 myButton을 부모 클래스형으로 형 변환

 
2. as! as?로 downcasting

  • 다운캐스팅은 안전한 변환을 보장할 수 없음
  • 유효하지 않은 형 변환이 이뤄졌는데 컴파일러가 에러를 잡지 않았다면, 런타임에서 에러가 발생
  • 다운캐스팅은 주로 자식 클래스로 변환하는 데 사용
  • 성공 확신이 있으면 as! 키워드를 사용하며 강제 변환 (forced conversion)
    변환이 안 되면 crash
  • 성공 확신이 없으면 as?를 사용하여 안전하게 변환
    변환이 안 되면 nil을 리턴하므로 옵셔널 타입으로 반환함
  • 부모인스턴스 as! 자식클래스
    downcasting 일반 타입으로 반환 (다운캐스팅이 반드시 성공할 것이라는 확신이 있을 때)
  • 부모인스턴스 as? 자식클래스
    downcasting 옵셔널 타입으로 반환 (다운캐스팅 성공에 확신이 없을 경우)

 
# 타입 검사 (is)
is 키워드를 이용하여 값의 타입 검사 (type check)

  • 지정된 객체가 MyClass라는 이름의 클래스의 인스턴스인지 검사
  • 인스턴스가 해당 클래스인가? : 인스턴스 is 클래스
if myobject is MyClass {
	// myobject는 MyClass의 인스턴스이다
}

 
# AnyObject

  • AnyObject can represent an instance of any class type
  • 범용 타입
  • 상속관계가 아니더라도 타입 캐스팅 가능한 타입
  • 어떤 클래스의 객체도 저장 가능
  • 가장 추상화된 최상위 클래스 (Obj-C의 NSObject)
  • 클래스만 허용하며 구조체나 열거형은 허용하지 않음

 
# Any

  • Any can represent an instance of any type at all, including function types.
  • 클래스, 구조체, 열거형, 함수타입도 가능