enum Optional<Wrapped>{
case some(Any) // 값이 존재하는 경우
case none // 값이 존재하지 않은 경우
}
Optional.none의 케이스로 값이 만들어진 것이 nil값 이다.
var value: Optional<Any> = nil
print(value)
##################################################################
>>> nil
##################################################################
var value: Any? = nil
print(value)
##################################################################
>>> nil
let valueNone = Optional<Int>.none
let valueNil: Int? = nil
print(valueNone)
print(valueNil)
#########################################
>>> nil
>>> nil
enum myOptional<Wrapped> {
case some(Any)
case none
}
//옵셔널 값이 있다면 어떤 타입이든 상관없다는 Optional
if value != nil {
#code
} else {
#code
}
//이런식의 코드 작성보다는 "**옵셔널 바인딩**"을 사용함
//if let
if let value = num {
#code
} else {
#code
}
// -> 만약 값이 nil 이라면 앱이 꺼지지 않고 else문 실행
//guard let
guard let value1 = num1 else { return }
guard let value2 = num2 else {
print("Jack: 어디까지 알아보셨나요?")
}
// -> guard 안의 조건문이 참(true)이 아니면 else문 실행
//while let 도 사용가능
var num: Int?
num = 1
if let value = num {
print(value)
} else {
print("nil")
}
value = 2 <<< 에러!
extension ViewController : UITableViewDataSource
{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? CustomTableViewCell else {return UITableViewCell()}
return cell
}
}
func earlyExit(num: Int?) {
guard let unwrappedNum = num,
unwrappedNum < 10, // 여기서 , 는 AND 논리연산(&&)과 동일
unwrappedNum >= 0 else {
print("잘못된 숫자를 입력하셨습니다.")
return
}
print("입력한 숫자는 \\(unwrappedNum) 입니다.")
}
var num1: Int
num1 = 3
print(num1)
var num2: Int?
//num2 = Optional(3) -> 원칙
num2 = 3 -> 허용
print(num2)
print("num1: \\(num1), num2: \\(num2)", num1 == num2) //true
//형태
let num: Int!
print(type(of: num)) // Optional<Int>.Type -> IUO 역시 옵셔널 타입
let num100: Int! = 1
print(num100) // Optional(1) -> 옵셔널 추출이 안됨
//기존 옵셔널
var num1: Int? = 4
var num2: Int = num1 // Value of optional type 'Int?' must be unwrapped to a value of type 'Int' 에러
var num3: Int! = 4
var num4: Int = num3
print(num4) // 4 -> 옵셔널 해제
@IBOutlet weak var tableView: UITableView! // 프로퍼티 지연 초기화
//위의 경우와 API에서 IUO를 리턴한 경우를 제외하고 옵셔널 바인딩 사용을 추천
//map()은 기존 데이터를 변형하여 새로운 컨테이너를 만든다
// 기존 데이터는 변형되지 않는다(데이터 유지)
let intArray = [1,2,3,4,5]
let mappedIntArray = intArray.map { String($0) }
print(mappedIntArray)
>>> ["1", "2", "3", "4", "5"]
// 문자열이 정수로 바꿀 수 없는 문자열이라면?
let stringArray = ["Jack", "Hue", "Bro", "1"]
let mappedStringArray = stringArray.**map** { Int($0) }
print(mappedStringArray)
>>> [nil, nil, nil, Optional(1)]
let stringArray = ["Jack", "Hue", "Bro", "1"]
let mappedStringArray = stringArray.**compactMap** { Int($0) }
print(mappedStringArray)
>>> [1] // 모든 옵셔널 언래핑, nil값 포함 x
//1. not-nil인 결과들을 가지는 배열을 리턴
let array: [Int?] = [1, 2, 3, 4, nil]
let mentoArr: [String?] = ["jack", "hue", "bro", nil]
print(array)
print(mentoArr)
>>> [Optional(1), Optional(2), Optional(3), Optional(4), nil]
>>> [Optional("jack"), Optional("hue"), Optional("bro"), nil]
===============================================================
//Int?
let flatMappedArray = array.flatMap { $0 }
print(flatMappedArray)
>>> [1, 2, 3, 4] // 옵셔널 해제, nil값은 출력 안됨
//String?
let flatMappedMentoArray = mentoArr.flatMap { $0 }
print(flatMappedMentoArray)
>>> ["jack", "hue", "bro"] // 옵셔널 해제, nil값은 출력 안됨
//flatMap 대신 compactMap() 사용 -> 같은 결과
===============================================================
//주어진 시퀀스 내의 요소들을 하나의 배열로써 리턴
let arrayInArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let flatMappedArray2 = arrayInArray.flatMap { $0 }
print(flatMappedArray2)
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]
let intArray2: [[Int?]] = [[1, 2, 3], [nil, 4], [5, nil], [nil, 6]]
let flatMapIntArr = intArray2.flatMap { $0 }
let compactMapIntArr = intArray2.compactMap { $0 }
print(flatMapIntArr)
print(compactMapIntArr)
>>> [Optional(1), Optional(2), Optional(3), nil, Optional(4), Optional(5), nil, nil, Optional(6)]
>>> [[Optional(1), Optional(2), Optional(3)], [nil, Optional(4)], [Optional(5), nil], [nil, Optional(6)]]
=====================================================================================================
let intArray2: [[Int?]] = [[1, 2, 3], [nil, 5], [6, nil], [nil, nil]]
let flatMapArr = intArray2.flatMap { $0 }.compactMap{ $0 }
print(flatMapArr)
>>> [1, 2, 3, 5, 6]
struct Human {
var name: String?
var man: Bool = true
}
struct Privacy {
var student: Human?
var address: String?
}
var sesac2nd: Privacy? = Privacy(student: Human(name: "DY", man: true), address: "Seoul")
sesac2nd?.student // 1. sesac2nd는 옵셔널 타입이기 때문에 sesac2nd.student로 호출 불가
sesac2nd?.student?.name // 2. sesac2nd, student는 옵셔널 타입이므로 sesac2nd.student.name로 호출 불가
sesac2nd?.student?.name = "Mime" // 3. 값 할당 -> 안정성 검사 불필요
##### sesac2nd 변수를 이용하여 student 프로퍼티의 내부 프로퍼티인 name을 참조하기 #####
######################## 옵셔널 체이닝 X ############################
if let mimeMan = sesac2nd {
if let mimeStudent = mimeMan.student {
if let mimeName = mimeStudent.name {
print("나는 \(mimeName) 입니다.") // 나는 DY 입니다.
}
}
}
-> 좀 더 간결하게?
if let mimeMan = sesac2nd!.student!.name {
print("나는 \(mimeMan) 입니다.")
}
// 중간에 nil 값이 존재한다면? -> 런타임 오류
######################## 옵셔널 체이닝 O ############################
if let mimeMan = sesac2nd?.student?.name {
print("나는 \(mimeMan) 입니다.")
}
1.에서 sesac2nd가 nil이 아니면 student객체가 반환되고, nil이면 nil값을 반환한다. = 2.
print(sesac2nd?.student)
print(sesac2nd?.student?.name)
var sesac2nd2: Privacy? = nil
print(sesac2nd2?.student)
print(sesac2nd2?.student?.name)
##################################################################
>>> Optional(__lldb_expr_23.Human(name: Optional("DY"), man: true))
>>> Optional("DY")
>>> nil
>>> nil
1., 2. 에서 맨 마지막 값은 옵셔널 체이닝을 통해 참조하기 때문에 옵셔널 바인딩이 필요하다
if let name = sesac2nd?.student?.name {
print(name)
}
let name2 = sesac2nd?.student?.name
print(name2)
##################################################################
>>> DY
>>> Optional("DY") // 일반 값일 지라도 옵셔널 체인을 통해 참조했다면 옵셔널 타입으로 변경
##################################################################
class CustomObservable<T> {
private var listener: ((T) -> Void)?
var value: T {
didSet {
listener?(value)
}
}
init(_ value: T) {
self.value = value
}
func bind(_ closure: @escaping (T) -> Void) {
closure(value)
listener = closure
}
}
var value: T {
didSet {
listener?(value) // listener가 옵셔널 클로저 타입이기 때문에
}
}
var name: String? = "jack"
print(name)
if let mento = name {
print("i'm \\(mento)")
} else {
print("nil")
}
>>> Optional("jack")
>>> i'm jack
//할당연산자, 임시 상수 사용안해도 됨
name = "Hue"
if let name {
print("my name is \\(name)")
} else {
print("nil입니다.")
}
>>> my name is Hue
//단 객체 내부의 프로퍼티에는 적용되지 않음
struct Phone {
var number: String
}
let phone: Phone? = Phone(number: "010-1111-2222")
if let phone.number {
print("jack: \\(phone.number)")
}
[swift / iOS] UIAlert, Custom Alert (0) | 2022.11.18 |
---|---|
[App Store] 날짜관련 앱에서 충돌이 난다면..? (1) | 2022.10.11 |
[iOS/Swift ] UITableViewCell에서의 타입 캐스팅 (0) | 2022.10.11 |
[iOS/Swift ] for ~ in VS forEach (0) | 2022.10.11 |
[Swift] 다른 파일의 메서드 호출하기 (0) | 2022.08.13 |