반응형
1. 자료구조
배열(Array)
- 데이터를 순차적으로 저장하는 자료구조
- 인덱스를 사용해 특정 요소에 접근
- 특징: 빠른 조회(O(1)), 삽입/삭제 시 성능 저하(O(n))
var numbers = [1, 2, 3, 4, 5]
numbers.append(6)
print(numbers) // [1, 2, 3, 4, 5, 6]
큐(Queue)
- 선입선출(FIFO, First In First Out) 구조
- 데이터를 한쪽에서 삽입하고, 반대쪽에서 제거
- 사용 사례: 프린터 작업 대기열, BFS 탐색
struct Queue<T> {
private var elements: [T] = []
mutating func enqueue(_ element: T) {
elements.append(element)
}
mutating func dequeue() -> T? {
return elements.isEmpty ? nil : elements.removeFirst()
}
}
궁금한점 🔎
mutating 이란 무엇인가?
[ Swift ] mutating
사전캠프 과제를 통해 한 번도 사용해보지 않은 mutating 키워드에 대해 다시 한 번 깊이 알아보자. Swift에서 mutating 키워드는 구조체(struct) 또는 열거형(enum) 내부에서 인스턴스의 속성을 변경할
sheep1sik.tistory.com
스택(Stack)
- 후입선출(LIFO, Last In First Out) 구조
- 데이터를 한쪽에서 삽입하고 제거
- 사용 사례: 함수 호출 스택, 괄호 검사
struct Stack<T> {
private var elements: [T] = []
mutating func push(_ element: T) {
elements.append(element)
}
mutating func pop() -> T? {
return elements.popLast()
}
}
2. 메모리 구조 및 ARC
- 메모리 구조
- Stack: 함수 호출, 지역 변수 저장
- Heap: 동적 메모리 할당, 참조 타입(클래스) 저장
- Code: 실행 중인 코드 저장
- Data: 전역 변수, 정적 변수 저장
- ARC(Automatic Reference Counting)
- Swift의 메모리 관리 방식
- 클래스 인스턴스의 참조 횟수를 추적하여 필요하지 않은 인스턴스를 메모리에서 해제
- 순환 참조(Circular Reference)
- 두 개 이상의 객체가 서로를 참조하면서 메모리에서 해제되지 않는 상황
- 해결 방법
- weak 또는 unowned 키워드 사용
🛠 순환 참조 해결 예제
class Person {
var name: String
var pet: Pet?
init(name: String) {
self.name = name
}
}
class Pet {
var owner: Person?
}
let person = Person(name: "Alice")
let pet = Pet()
person.pet = pet
pet.owner = person // 순환 참조 발생
해결 방법: weak 키워드
💡 직접 구현해보기
Step 1: 자료구조 구현
- 큐(Queue) 구현하기:
- 정수를 저장하는 Queue 구조체를 구현하세요.
- enqueue()로 데이터를 삽입하고, dequeue()로 데이터를 제거합니다.
- 큐의 현재 상태를 출력하는 메서드를 추가하세요.
- 스택(Stack) 구현하기:
- 문자열을 저장하는 Stack 구조체를 구현하세요.
- push()로 데이터를 삽입하고, pop()으로 데이터를 제거합니다.
- 스택의 최상단 값을 반환하는 메서드를 추가하세요.
import UIKit
// 큐 ( 선입 선출, FIFO )
struct Queue {
private var elements : [Int] = []
mutating func enqueue(_ element: Int) {
elements.append(element)
}
mutating func dequeue() -> Int? {
// elements 배열이 비어있다면 nil 반환 , 비어있지 않다면 배열 제일 앞 숫자 제거
return elements.isEmpty ? nil : elements.removeFirst()
}
func printQueue() {
print("Queue : ", elements)
}
}
// 스택 ( 후입선출, LIFO )
struct Stack {
private var elements: [String] = []
mutating func push(_ element: String) {
elements.append(element)
}
mutating func pop() -> String? {
// elements 배열의 가장 마지막 제거
return elements.popLast()
}
func top() -> String? {
// elements 마지막 반환
return elements.last
}
func printStack() {
print("Stack : ", elements)
}
}
var queue = Queue()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
queue.printQueue()
print("Dequeued:", queue.dequeue() ?? "nil")
queue.printQueue()
var stack = Stack()
stack.push("A")
stack.push("B")
stack.push("C")
stack.printStack()
print("Top Element:", stack.top() ?? "nil")
print("Popped:", stack.pop() ?? "nil")
stack.printStack()
Step 2: ARC와 순환 참조 해결
- 순환 참조 문제 구현:
- 두 클래스를 생성하세요:
- Person 클래스: 이름을 저장하는 속성(name)과 애완동물(pet) 속성을 가짐.
- Pet 클래스: 주인(owner) 속성을 가짐.
- 서로를 참조하는 인스턴스를 생성하고 순환 참조 문제를 확인하세요.
- 두 클래스를 생성하세요:
- 순환 참조 해결:
- weak 키워드를 사용해 순환 참조 문제를 해결하세요.
- 해결 후, 두 인스턴스가 정상적으로 메모리에서 해제되는지 확인하세요.
import UIKit
class Person {
var name: String
var pet: Pet?
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinit")
}
}
class Pet {
var name: String
weak var owner: Person?
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinit")
}
}
// 순환 참조 확인
var person: Person? = Person(name: "양원식")
var pet_1: Pet? = Pet(name: "뭉치")
var pet_2: Pet? = Pet(name: "큐티")
person?.pet = pet_1
pet_1?.owner = person
pet_2?.owner = person
// 인스턴스 해제
person = nil
pet_1 = nil
pet_2 = nil
반응형
'내배캠 iOS 마스터 6기' 카테고리의 다른 글
[ 사전캠프 6일차 ] 비동기 프로그래밍/ 제네릭 (0) | 2025.02.10 |
---|---|
[ 사전캠프 4일차 ] 클로저/ 객체지향 프로그래밍 (0) | 2025.02.06 |
[ 사전캠프 1일차 ] Struct와 Class / 프로토콜 (0) | 2025.02.04 |