1. 기본 개념
- Class란 구조체(struct)와 비슷한 것이다
- 관계가 있는 것들을 묶어서 표현
- Object = Data + Method
- Object → Structure와 Class를 이용해 구현
- Data → Property
- Method → Method
- Structure 메모리 관리 타입 -> Stack
- Fast - 당장실행 해야하거나, 컨트롤, 매니징 해야하는 것들
- 함수에서 변수를 만들면 스택에 생성되고 계산이 끝나고 리턴하게 되면 스택에서 제거
- Fast - 당장실행 해야하거나, 컨트롤, 매니징 해야하는 것들
- Class 메모리 관리 타입 → Heap
- Slow - Class같은 ref데이터를 저장하는데 사용합니다
- Heap은 스택처럼 자동으로 데이터를 저장하지 않기 때문에 신경을 많이 써주어야한다.
- 변수선언시 힙과 스택의 변화
- 클래스 선언 → Heap 에 저장
- 변수 선언 → 스택에 저장
- 변수의 데이터가 class면 ref타입 이므로 Heap 에 저장된 데이터를 주소로 가짐(stack에서)
2. 클래스 인스턴스의 생성과 소멸
- Stored Property에 값을 저장할때에는 기본값을 지정해 주어야 한다.
- 스위프트의 모든 인스턴스는 초기화와 동시에 모든 프로퍼티에 유효한 값이 할당되어 있어야 합니다.
프로퍼티에 미리 기본값을 할당해두면 인스턴스가 생성됨과 동시에 초기값을 지니게 됩니다. - 하지만 이런 초기값을 나중에 상황에 따라 만들고 싶다면 키워드 init을 활용하게 됩니다.
- 1. Initializer
- designated( 메인 초기값) and convenience( 보조 초기값 ) initialization의 규칙
- DI는 자신의 부모의 DI를 호출해야 한다
- CI는 같은 클래스의 이니셜라이저를 꼭 하나 호출해야한다
- CI는 궁극적으로는 DI를 호출해야 한다
- 모든 파라미터의 초기값을 세팅하지 않을때 convenience init 을 쓸수 있다
- designated( 메인 초기값) and convenience( 보조 초기값 ) initialization의 규칙
- 1. Initializer
class Person {
var name: String
var age: Int
var nickName: String
}
// 이니셜라이저
init(name: String, age: Int, nickName: String) {
self.name = name
self.age = age
self.nickName = nickName
}
}
let hyeongyu: Person = Person(name: "hyeongyu", age: 29, nickName: "현규")
1. Optional Initializer
- 만약 클래스안에 있는 프로퍼티가 있을지 없을지 확신할수 없는 경우 Optional을 사용할수 있다
- 하지만 이렇게 옵셔널을 사용할 경우 initalizer를 두번사용하여 옵셔널 값이 있는 경우 없는경우를 둘다 작성해 주어야한다.
- override init은 먼저 세팅된 초기값을 변경할때 사용할수 있다.
- 상속받는 부모 클래스의 init은 super.init 키워드로 사용할 수 있다
- 상속받은 부모 클래스의 super.init을 사용해야 할때 주의 할점은 먼저 상속된 클래스의 stored property의 값들을 먼저 할당해 주어야 한다는 것이다
- two phase initializations (클래스 생성시 지켜야할 두가지 단계)
- 최하위 상속클래스의 store property의 초기값을 세팅하고
- 상속받은 클래스의 값을 세팅하기
- Phase 1 - All Stored Property have to be initialized = 이 페이즈 1이 끝나기 전에는 어떤 프로퍼티나 메서드를 사용할수 없습니다.
- Phase 2 - Phase 1 의 반대방향으로 프로퍼티나 메서드를 가능하게 한다. = 따라서 먼저 스토어드 프로퍼티를 자식프로퍼티 → 부모프로퍼티 → 메서드작성 의 순서로 작성해야한다.
// optional initializer 사용시
class PersonC {
var name: String
var age: Int
var nickName: String? // var nickName: String? optional 사용
}
// 이니셜라이저
//convenience 키워드는 init의 내용이 겹칠때 이미 선언된 init을 사용할때 사용한다.
convenience init(name: String, age: Int, nickName: String) {
self.init(name: name, age: age)
self.nickName = nickName
}
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
- 암시적 추출 옵셔널
- 인스턴스 사용에 꼭 필요하지만 초기값을 할당하지 않고자 할때 사용한다. ! 사용
class Puppy {
var name: String
var owner: PersonC!
init(name: String) {
self.name = name
}
func goOut() {
print("\(name)가 주인 \(owner.name)와 산책을 합니다")
}
}
//위의 클래스를 상속받아 변수를 선언합니다.
// 현재 오너가 없는 상태입니다. 하지만 꼭 필요합니다
let happy: Puppy = Puppy(name: "happy")
happy.goOut() //--> 아직 오너가 없기때문에 런타임 에러가 발생합니다. 현재오너값 nil
// 오너에 값을 넣어주기
happy.owner = jenny
happy.goOut() // 이때에는 happy가 주인 jenny와 산책을 합니다 가 출력됩니다.
- 실패 가능한 이니셜라이저
- 만약 매개변수로 전달되는 초기값이 잘못된 경우 인스턴스 생성에 실패하게 만드는 것 입니다.
- 생성에 실패하면 nil을 반환합니다
- 그래서 실패가능한 이니셜라이저의 반환타입은 옵셔널 타입입니다.
- 따라서 옵셔널 init을 사용하게 되면 반환값이 nil이 나올수 있기 때문에 클래스상속할때에 let John: PersonD? 라고해야 컴파일 에러가 나지 않습니다.
class PersonD {
var name: String
var age: Int
var nickName: String?
// if문안에 있는 조건을 만족하면 return nil로 인스턴스가 nil로 선언되어 반환됩니다.
init?(name: String, age: Int) {
if (0...120).contains(age) == false {
return nil
}
if name.count == 0 { // count가 0이라는 것은 "" 문자열이 없다는 것입니다
return nil
}
self.name = name
self.age = age
}
}
2. Deinitializer
- deinit은 클래스가 인스턴스의 메모리에서 해제되는 시점에 호출됩니다
- 인스턴스가 해제되는 시점에 해야할 일을 구현할 수 있습니다.
- 해제되는 시점은 ARC(Automatic Reference Counting)에 의해서 정해집니다.
- 클래스의 연결이 단 하나라도 살아있는경우 해제되지 않습니다.
- Deinitializer는 클래스 타입에서만 사용가능합니다.
class PersonE {
var name: String
var pet: Puppy?
var child: PersonC
init(name: String, child: PersonC) {
self.name = name
self.child = child
}
// 인스턴스가 메모리에서 해제되는 시점에 자동 호출
deinit {
if let petName = pet?.name {
print("\(name)가 \(child.name)에게 \(petName)를 인도합니다")
self.pet?.owner = child
}
}
}
var donald: PersonE? = PersonE(name: "donald", child: jenny)
donald?.pet = happy
donald = nil // donald 인스턴스가 더이상 필요없으므로 메모리에서 해제됩니다
// donald가 jenny에게 happy를 인도합니다
'IOS > Swift' 카테고리의 다른 글
[TIL] Swift. dequeueReusableCell (0) | 2020.10.09 |
---|---|
[TIL] Swift. Class 2편 (0) | 2020.10.07 |
[TIL] Swift. Method (0) | 2020.10.06 |
[TIL] Swift. Property (0) | 2020.10.01 |
[TIL] Swift. Structure(Class, Struct, Enum) (0) | 2020.09.30 |