[iOS] 옵셔널? Optional?

Madeline👩🏻‍💻·2023년 2월 23일
0

iOS study

목록 보기
1/61
post-thumbnail

첫 iOS 관련 글이다 키키

업로드중..

0. 옵셔널이란?

Swift가 가지고 있는 가장 큰 특징 중 하나가 바로 옵셔널 Optional 이다.

  • 값이 있을 수도, 없을 수도 있음을 표현
  • nil이 할당 될 수 있는지 없는지 표현

=> 안드로이드 코틀린 입장에서는 nullable에 해당하는 것 같다.
또 스위프트에서는 null 이 아닌 nil 로 표기한다.

// someOptionalParm에 nil이 할당 될 수 있다.
func someFunction(someOptionalParam: Int?) {
       // ....
}

/// someOptionalParm에 nil이 할당 될 수 없다.
func someFunction(someOptionalParam: Int) {
       // ....
}

someFunction(someOptionalParam: nil)
// someFunction(someParam: nil) 

1. 쓰는 이유?

1) 명시적 표현

  • nil의 가능성을 코드만으로 표현가능
  • 문서/주석 작성 시간 절약

2) 안전한 사용

  • 전달받은 값이 옵셔널이 아니라면 nil 체크를 하지 않고 사용가능
  • 예외 상황을 최소화 하는 안전한 코딩
  • 효율적 코딩

2. 문법과 선언

옵셔널 문법 = enum + generics (수업 후반에 다시 배울거에요)

연산자 : ??

1) 옵셔널 선언

enum Optional<Wrapped>: ExpressibleByNiliteral {
         case none
         case some(Wrapped)
}

let optionalValue: Optional<Int> = nil
let optionalValue: Int? =nil

2) 콜렉션 옵셔널

  • 배열
var array1 : [String]? //배열이 없을 수도 있음.
var array2 : [String?] //배열은 있으나 안에 원소가 옵셔널로 들어갈 수 있습니다.

3. 옵셔널 표현 - ! ?

1) 느낌표 !

// Implicitly Unwrapped Optional
var implicitlyUnwrappedOptionalValue: Int! = 100

switch implicitlyUnwrappedOptionalValue {
case .none:
    print("This Optional variable is nil")
case .some(let value):
    print("Value is \(value)")
}

// 기존 변수처럼 사용 가능
implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1

// nil 할당 가능
implicitlyUnwrappedOptionalValue = nil

// 잘못된 접근으로 인한 런타임 오류 발생
//implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1

2) 물음표 ?

// Optional
var optionalValue: Int? = 100

switch optionalValue {
case .none:
    print("This Optional variable is nil")
case .some(let value):
    print("Value is \(value)")
}

// nil 할당 가능
optionalValue = nil

// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이므로 연산불가
//optionalValue = optionalValue + 1

4. 옵셔널 바인딩

옵셔널 바인딩은 옵셔널의 값이 존재하는지를 검사한 뒤, 존재한다면 그 값을 다른 변수에 대입시켜줍니다.

  • nil 체크 + 안전한 추출
  • if-else 방식 사용

1) if

if let realStr = optionalStr {
	print("문자열의 값 \(realStr)")
}
else {
	print("문자열이 nil이다.");
}

2) guard

func bindingWithWhere() {
	guard let val = nilAvailable, val > 0 else {
    	return;
    }
    
    print("val은 유효하고 0보다 큰 값이다, \(val)")
}

-> 콤마 써서 여러 옵셔널을 바인딩 할 수 있다

3) 콤마 써서 여러개 바인딩

  • 단, 모든 옵셔널에 값이 있을 때만 작동함
// ,를 사용해 한 번에 여러 옵셔널을 바인딩 할 수 있습니다
// 모든 옵셔널에 값이 있을 때만 동작합니다
myName = "yagom"
yourName = nil

if let name = myName, let friend = yourName {
    print("\(name) and \(friend)")
}
// yourName이 nil이기 때문에 실행되지 않습니다
yourName = "hana"

if let name = myName, let friend = yourName {
    print("\(name) and \(friend)")
}
// yagom and hana

5. 옵셔널 체이닝

왕ㅇ 이거 코틀린이랑 진짜 비슷하다

// 옵셔널 체이닝
let array: [String]? = []
var isEmptyArray = false

if let array = array, array.isEmpty {
  isEmptyArray = true
} else {
  isEmptyArray = false
}

isEmptyArray

// 위 코드랑 아래랑 똑같음 간결하게 해주는게 체이닝

let isEmptyArray2 = array?.isEmpty == true

6. 공부한 코드

//1. console Log and string
//  1) print
//  2) dump

import Swift

let age : Int = 10

print("Hi I'm \(age) years old\n")

class Person{
    var name : String = "Maddy"
    var age = 10
}

let Maddy: Person = Person()

print(Maddy)

print("\n###############\n")

dump(Maddy)

//2. var and const

//  1) const : let
//  2) var : var

//let constName : Type = value

//var varName : Type = value

let constant : String = "cannot change constant let"
var variable : String = "var"

variable = "can be changed into different value"
//constant = "this one can't"

//lateinit = type을 꼭 써줘야함
let sum : Int
let inputA = 100
let inputB = 200
sum = inputA + inputB
print("sum = ", sum)
//print(type(of: inputB))

//3. type

//Bool, Int, UInt, Float, Double, Character, String

//Bool
var someBool : Bool = true
someBool = false
print("someBool = ", someBool)

//Int
var someInt : Int = -100
print("someInt = ", someInt)

//UInt : + Int
var someUInt : UInt = 100
print("someUInt = ", someUInt)
//someUInt = someInt //=> error

//Float
var someFloat : Float = 3.14
someFloat = 3
print("someFloat = ", someFloat)

//Double
var someDouble : Double = 3.14
someDouble = 3
//someDouble = someFloat //=>error

//Character => 한글자
var someCharacter : Character = "🙊"
var someCharacter2 : Character = "m"
var someCharacter3 : Character = "가"
print(someCharacter)
print(someCharacter2)
print(someCharacter3)

//String
var someString : String = "monkey 🙈"
someString = someString + "cute"
print(someString)


//4. type (2)
/*
 Any : Swift 의 모든 타입을 지칭하는 키워드
 AnyObject : 모든 클래스 타입을 지칭하는 프로토콜
 nil : null
 */
var someAny : Any = 100
someAny = "any type is available"
someAny = 123.12
//someAny = nil // => error 'nil' cannot be assigned to type 'Any'

class SomeClass{}
var someAnyObject : AnyObject = SomeClass()
//someAnyObject = 123.12 //=> error


//5. collection
//array, dictionary, set

var integers : Array<Int> = Array<Int>()
integers.append(1)
integers.append(100)
integers.append(10)

integers.contains(100)
integers.contains(99)
integers[0]

integers.remove(at : 0)
integers.removeAll()

integers.count

//Array<Double> = [Double]
var doubles : Array<Double> = [Double]()
var doubles1 : [Double] = [Double]()
var doubles2 : Array<Double> = []
var doubles3 : Array<Double> = Array<Double>()

var strings : [String] = [String]()

var characters : [Character] = []

let immutableArray = [1,2,3]
//immutableArray.append(4) //=>error

var anyDictionary : Dictionary<String, Any> = [String:Any]()
anyDictionary["someKey"] = "value"
anyDictionary["anotherKey"] = 100

anyDictionary["someKey"] = "dictionary"

anyDictionary.removeValue(forKey: "anotherKey")

anyDictionary["someKey"] = nil
//얘는 왜 되는거지??

//불변 Dictionary: let을 사용하여 Dictionary 선언
let emptyDictionary: [String: String] = [:]
let initalizedDictionary: [String: String] = ["name": "yagom", "gender": "male"]

var integerSet : Set<Int> = Set<Int>()
integerSet.insert(1)
integerSet.insert(10)
integerSet.insert(100)

integerSet.contains(1)

let setA : Set<Int> = [1,2,3,4,5]
let setB : Set<Int> = [3,4,5,6,7]
let union : Set<Int> = setA.union(setB)
let sortedUnion : [Int] = union.sorted()
let intersection : Set<Int> = setA.intersection(setB)
let subtracting : Set<Int> = setA.subtracting(setB)

//6. function

func sum(a:Int, b:Int) -> Int{
    return a+b
}

sum(a:0, b:0)

//returns nothing
func printName(name : String) -> Void{
    print(name)
}

func printYourName(name : String){
    print(name)
}

printName(name: "Maddy")
printYourName(name: "Maddy")

func maximumIntegerValue() -> Int{
    return Int.max
}

maximumIntegerValue()

//7. function(2)

//매개변수 기본값
func greeting1(friend : String, me : String = "Maddy"){
    print("Hello \(friend), I'm \(me)")
}

greeting1(friend: "FF")

//전달인자 레이블
func greeting2(to friend : String, from me : String){
    print("Hello \(friend), I'm \(me)")
}

greeting2(to: "FF", from : "GG")

//가변 매개변수
func hello(me : String, friends : String...) -> String{
    return "Hello \(friends)!"
}

print(hello(me: "Maddy", friends: "GG", "ee", "ss"))

//함수 타입
var someFunction : (String, String) -> Void = greeting2(to:from:)
someFunction("gg", "GG")

func runAnother(function : (String, String) -> Void){
    function("jenny", "mike")
}
runAnother(function: greeting1(friend:me:))

//8. if, else, switch, for, while

let someInteger = 100
if(someInteger < 100){
    print("under 100")
}
else if(someInteger > 100){
    print("above 100")
}
else{
    print("100")
}

//switch
switch someInteger {
case 0 :
    print("zero")
case 1..<100:
    print("1~99")
case 100:
    print("100")
case 101...Int.max:
    print("over 100")
default:
    print("unknown")
}

var integers2 = [1,2,3]
let people = ["maddy": 10, "eric": 15, "mike":12]
for i in integers2{
    print(i)
}
for (name, age) in people{
    print("\(name): \(age)")
}

//while

while integers2.count>0{
    print(integers2)
    integers2.removeLast()
}

var integers3 = [1,2,3]
//repeat - while
repeat{
    print(integers3)
    integers3.removeLast()
}while integers3.count > 0


//9. optional (nullable)
//값이 있을 수도 있고 없을 수도 있음

//enum Optional<Wrapped>:ExpressibleByNilLiteral{
//    case none
//    case some(Wrapped)
//}

//let optionalValue: Optional<Int> = nil
//let optionalValue: Int? = nil

// !!!!!!!!!!!!!!!!!!!!!!!!!!!
// Implicitly Unwrapped Optional
var implicitlyUnwrappedOptionalValue: Int! = 100

switch implicitlyUnwrappedOptionalValue {
case .none:
    print("This Optional variable is nil")
case .some(let value):
    print("Value is \(value)")
}

// 기존 변수처럼 사용 가능
implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1

// nil 할당 가능
implicitlyUnwrappedOptionalValue = nil

// 잘못된 접근으로 인한 런타임 오류 발생
//implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1

//???????????????????????????
// Optional
var optionalValue: Int? = 100

switch optionalValue {
case .none:
    print("This Optional variable is nil")
case .some(let value):
    print("Value is \(value)")
}

// nil 할당 가능
optionalValue = nil

// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이므로 연산불가
//optionalValue = optionalValue + 1

//10. optional (2)

/*
 옵셔널 바인딩
 1. nil 체크 + 안전한 추출
 2. 옵셔널 안에 값이 들어있는지 확인하고 값이 있으면 값을 꺼내옵니다.
 3. if-let 방식 사용
 */


// 옵셔널 체이닝
let array: [String]? = []
var isEmptyArray = false

if let array = array, array.isEmpty {
  isEmptyArray = true
} else {
  isEmptyArray = false
}

isEmptyArray

// 위 코드랑 아래랑 똑같음 간결하게 해주는게 체이닝

let isEmptyArray2 = array?.isEmpty == true

🐶 reference

https://www.boostcourse.org/mo122/lecture/11240?isDesc=false

https://devxoul.gitbooks.io/ios-with-swift-in-40-hours/content/Chapter-2/optionals.html

https://velog.io/@ym980118/Swift-nil과-옵셔널

profile
🍎 Apple Developer Academy@POSTECH 2기, 🍀 SeSAC iOS 4기

0개의 댓글