문과 코린이의, [IOS] 기록/Swift 이론

[문과 코린이의 IT 기록장] IOS Swift - nill과 Optional ( nil이란?, 옵셔널 타입이란?, nil 대입이 에러가 나는 상황, nil 대입이 에러가 나는 상황, 옵셔널 타입의 특징, 자동으로 옵셔널이 되는 예시, 옵..

벼리네 2023. 5. 22. 09:16
반응형

[문과 코린이의 IT 기록장] IOS Swift - nill과 Optional ( nil이란?, 옵셔널 타입이란?, nil 대입이 에러가 나는 상황, nil 대입이 에러가 나는 상황, 옵셔널 타입의 특징, 자동으로 옵셔널이 되는 예시, 옵셔널이 콜렉션에서 어떻게 사용되는가?, 옵셔널 바인딩, nil 연산자, 옵셔널 체인, 강제 언래핑 (Forced Unwrapping) )

[문과 코린이의 IT 기록장] IOS Swift - nill과 Optional ( nil이란?, 옵셔널 타입이란?, nil 대입이 에러가 나는 상황, nil 대입이 에러가 나는 상황, 옵셔널 타입의 특징, 자동으로 옵셔널이 되는 예시, 옵셔널이 콜렉션에서 어떻게 사용되는가?, 옵셔널 바인딩, nil 연산자, 옵셔널 체인, 강제 언래핑 (Forced Unwrapping) )


1. nil이란?

- 다른 언어의 null(값이 할당되지 않은 상태)에 해당한다.

- 기본 타입 (Int / Bool)에도 nil이 가능하다.

- 값이 0과 값이 nil은 다른 것이다. 즉, 0은 값이 있는 상태이며, nil은 그 값조차 없는 상태이다.


2. 옵셔널 타입이란?

- 일반 변수 / 상수에는, nil 대입이 불가능하며, 옵셔널 타입만 가능하다.

- 즉 옵셔널 타입 nil을 다룰 수 있는 타입이다.

 * int + nil => 옵셔널 int 타입


3. nil 대입이 에러가 나는 상황

- 일반 변수 / 상수에 nil을 대입하는 상황

var i = 0 // 0의 값을 할당 함으로써 이것은 int 타입을 가지게 됨
i = nil // 일반 int 타입에 값을 할당하려 했으므로 에러 발생

4. nil 대입이 에러가 나는 상황

- 옵셔널 타입이란, nil 값을 가질 수 있는 변수 및 상수를 이야기한다.

- 이는 타입 뒤에 물음표(?)로 선언하며, 타입 선언을 필수적으로 해야 한다.

var optionalVar : Optional<Int>
var optionalVar2 : Int?
// 둘 다 가능
// nil값과 동시에 Int 값을 가질 수 있게 되었다는 뜻

5. 옵셔널 타입의 특징

1) nil 대입이 가능하다

var optionalVar : Int? = 3 // Optional Int로 설정했으므로 
optionalVar = nil // nil값 대입 가능

2) 자동 초기화가 가능하다

var optionalVar : Int?
print(optionalVar) // nill 출력

6. 자동으로 옵셔널이 되는 예시

- 내가 optional로 작성하지 않아도, 자동으로 optional이 되는 경우가 있음.

- 동작 결과가 nil이 될 가능성이 있을 때 주로 발생한다

 

1) 타입 변환

let intFromStr = Int("a") 
// a에 해당하는 숫자가 없기 때문에 nil값이 나옴.
// 따라서 intFromStr 는 Int Optional type이 되어야 함.

2) 딕셔너리

let numbers = ["one":1, "two":2]
let three = numbers["three"] 
// 딕셔너리에 없는 키를 대입했기 때문에, nil값을 가짐

7. 옵셔널이 콜렉션에서 어떻게 사용되는가?

1) 배열

var array1 : [String]? 
// 배열 자체가 옵셔널인 경우임. 배열은 값을 가질 수도 있고 없을 수도 있음.
var array2 : [String?]
// 배열 자체는 옵셔널이 아님. 배열은 반드시 값을 가져야 함.
// 그러나 배열에 있는 원소가 String 타입이거나 nil 값을 가질 수 있음.

2) 딕셔너리

var dic1 : [String : Int]?
// 딕셔너리 자체가 옵셔널인 경우임. 딕셔너리는 값을 가질 수도 있고 없을 수도 있음.
var dic2 : [String : Int?]
// 딕셔너리 자체는 옵셔널이 아님. 딕셔너리는 반드시 값을 가져야 함.
// 그러나 딕셔너리에 있는 원소가 String타입이거나 nil의 값을 가질 수 있음.

 


8. 옵셔널 바인딩

- 옵셔널 타입 객체를 사용할 때는, nil인 경우nil이 아닌 경우 고려해야 한다.

 

1) 잘못된 옵셔널 타입 사용의 예

- 컴파일 에러 발생

var optionalStr : String? = "ABC"
optionalStr.lowercased() // optionalType 직접 사용은 불가능.
// 이유 : 지금은 "ABC"라는 값을 가지고 있지만, 언젠가 nil이 될 수 있는 가능성이 있기 때문에

=> 이와 같이 옵셔널 타입의 객체들은 일반적으로 사용할 수 없으므로 다른 방법을 사용해야 한다.

 

2) 옵셔널 타입 객체 사용 방법

- 옵셔널 타입은 nil 또는 유효한 값을 가지게 된다.

- 따라서, 옵셔널 타입의 변수에서 유효한 값을 얻어오는 언래핑 과정이 필요하다.

- ifguard와 함께 사용하여 유효한 값을 얻어와 상수에 대입하는 방법을, 옵셔널 바인딩이라고 한다.

- 바인딩 된 타입일반(Non-Optional)타입으로 다룬다.

- nil인 경우는 else로 동작시킨다.

 

3) 옵셔널 바인딩 예시

(1) if를 사용한 옵셔널 바인딩

var optionalStr : String?

// (1) nil여부 판단 
// (2) 언래핑 과정 필요 : let retStr = optionalStr

if let realStr = optionalStr{ // nil이 아닌 경우
	print("nil이 아니다!")
}
else { // nil인 경우
	print("nil이다")
}

(2) guard를 사용한 옵셔널 바인딩

func bindingWithWhere(){
	guard let val = nilAvailable, var > 0 else { return }

	print("val은 유효하고 0보다 큰 값이다.")
}

(3) 다중 바인딩, 함수 호출 (옵셔널 타입 반환)

// 옵셔널 바인딩을 여러번 해야하는 경우가 있다면 ,를 이용해서 이렇게 할 수도 있다.
if let val1 = someFunc(),
   let val2 = anotherFunc()
{
    // 코드
}

(4) 옵셔널 바인딩 체인

// 옵셔널 바인딩을 체인 형태로 사용할 수도 있음
// 첫 번째 옵셔널 바인딩을 한 언래핑한 값의 결과가, val1에 들어갈 것임
// 그 언래핑한 val1값을 또 다시, 타입변환에 대한 옵셔널 바인딩을 넣어서 진행할 수 있음
if let val1 = nilAvailableStr,
   let val2 = Int(val1)
  {
  	// 코드
  }

(5) 옵셔널 바인딩과 조건 비교

if let val = someFunc(), condition == true{
	// 코드
}

9. nil 연산자

- nil일 경우, ??연산자 이후의 값을 사용한다.

- 기본값 설정을 할 때, 효과적으로 활용이 가능하다.

var userSelectedColor : String?
var colorName = userSelectedColor ?? "Red" // nil이면 Red를 사용

10. 옵셔널 체인

- 옵셔널 객체 ? 기호를 이용해서 직접 사용한다.

- ?를 사용한 평가 결과가 nil이면 진행하지 않고 nil을 반환한다.

- ?를 사용한 평가 결과가 nil이 아니면 계속 진행한다. (언래핑)

- 최종 결과옵셔널 타입이 된다.

- 이는 메소드 호출 / 프로퍼티 접근 / 배열 원소 접근 등에서 사용할 수 있다.

 

1) 옵셔널 체인 사용법

- 유효한 값일 경우

var optionalStr : String? = "ABC"
let str optionalStr?.lowercased()
// 결과는 Optional("abc")

- nil인 경우

var optionalStr:String? = nil
let str2 = optionalStr?.lowercased() 
// lowercased() 진행 불가로, 결과는 nil값

 

2) 프로퍼티 접근 / 메소드 호출 / 배열 및 딕셔너리 접근 등에서 사용법

let array : [String]? = ["A","B","C"]
let str3 = array?[1].lowercased()
// 배열이 [1]값을 가지므로 "B"를 반환
// 배열이 [1]값이 없으면 nil을 반환

11.  강제 언래핑 (Forced Unwrapping)

- !기호를 사용한다

- nil여부와 관계없이, 언래핑(옵셔널 타입의 변수에서 유효한 값을 얻어오는 방법)을 시도한다.

- 타입 선언이나, 옵셔널 체인에 사용한다.

 

1) 언래핑 결과

- nil이면 error 발생

- nil이 아니면 언래핑 진행

 

2) 강제 언래핑 예시

let intVal2 = Int("1")!
// intVal은 Int타입임. (Optional 타입 X)
let val = Int("A") // Error
// 타입 변환 실패 => nil값을 가지므로 Error 발생
let dictionary = ["one":1, "two":2]
let two = dictionary["two"]!
// two의 값이 있으므로 언래핑 성공
let three = dictionary ["three"]!
// three값은 가지고 있지 않으므로, nil값을 반환. 즉 error 발생

 

3) 강제 언래핑 사용 사례

- 객체 생성 (Failable Initializer)

- 메소드 호출 , 프로퍼티 접근

- 옵셔널 체인

 

4) 강제 언래핑과 옵셔널 체인

- 옵셔널 체인에, 강제 언래핑을 사용한 예시

- 언래핑 실패시 런타임 에러가 발생한다.

var optionalStr : String? = "ABC"
let str1 = optionalStr!.lowercased()

 

5) 암시적 언래핑 옵셔널 (Implicitly Unwrapping Optional, IUO)

- 타입 선언 뒤에 !를 사용한다.

- 이 또한 optional Type이기 때문에 nil을 다룰 수 있으며, 기본적으로 nil로 자동 초기화된다.

- 또한 자동으로 언래핑을 시도한다. (nil값 비교를 하지 않음)

- 즉, 언래핑 성공이 확실할 때 사용한다.

var iuoval : Int! = 123
iuoVal = nil
let iuoStr : String! = "Hello Swift"
iuoStr.lowercased() // 성공 (언래핑 성공)

iuoStr = nil
iuoStr.lowercased() // 런타임 에러 발생 (언래핑 실패)
반응형