DispatchQueue.global().async { // 작업을 글로벌 큐로 디스패치, 비동기로 실행
print("비동기 작업 실행")
// 비동기 작업이 실행되는 동안 기존의 큐 작업은 비동기 작업의 종료를 기다리지 않고 실행
Dispatch Queue.main.async { // 작업을 메인 큐로 디스패치, 비동기로 실행
print("UI 업데이트")
// UI 업데이트 작업 메인 큐에서 실행
}
}
DispatchQueue.global().async {
[1, 2, 3, 4, 5].forEach { print($0) }
DispatchQueue.main.async {
print("UI 업데이트 완료")
}
}
// 1 2 3 4 5 출력
→ 위 코드로는 1, 2, 3, 4, 5 출력 후 메인 스레드 자체가 종료되므로(다른 코드가 없으니) 메인 큐를 실행하지 못해 "UI 업데이트 완료"가 출력되지 않음
DispatchQueue.global().async {
[1, 2, 3, 4, 5].forEach { print($0) }
DispatchQueue.main.async {
print("UI 업데이트 완료")
}
}
dispatchMain() // 메인 런 루프(메인 스레드에서 발생하는 이벤트 처리 엔진) 실행
// 1 2 3 4 5
// UI 업데이트 완료 출력
→ dispatchMain() 코드로 메인 런 루프 실행 - 메인 큐에 등록된 코드 실행 : "UI 업데이트 완료" 정상 출력
func loadData() {
sleep(3)
print("Data")
}
DispatchQueue.global().async {
loadData()
DispatchQueue.main.async {
print("데이터 로드 완료")
}
}
dispatchMain()
// 3초 대기 후 "Data" , "데이터 로드 완료" 출력
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var a = 10
var b = 20
swapValues(&a, &b)
print(a, b) // "20 10" 출력
}
struct Stack<T> {
var arr: [T] = []
// 스택 요소 추가
mutating func push(_ element: T) {
arr.append(element)
}
// 스택 요소 제거
mutating func pop() {
arr.removeLast()
}
// 스택 현재 상태 출력
func status() {
print(arr)
}
}
var a = Stack(arr: ["a", "b"]) // 문자열 값으로 초기화하여 자동적으로 T를 String으로 타입 추론
a.push("c")
a.status() // ["a", "b", "c"] 출력
var b = Stack<Int>() // <Int>로 T의 타입을 선언
b.push(1)
b.status() // [1] 출력
struct Animal {
var name: String
var age: Int
}
var doggy = Animal(name: "Doggy", age: 3)
var doggy2 = doggy
doggy2.age = 4
print(doggy.age) // 3 출력
print(doggy2.age) // 4 출력
→ doggy2에 doggy를 할당하였지만 doggy2와 doggy는 별개의 인스턴스!
⇒ 그렇기 때문에 doggy2.age를 바꾸어도 doggy.age는 그대로 3을, doggy2.age는 변경된 값인 4를 출력
➡︎ 따라서 값 타입 내부 메소드에서 값 타입의 속성을 변경하면 별개의 인스턴스로 대체되어버림!
struct Animal {
var name: String
var age: Int
func grow() {
age += 1
}
}
var doggy = Animal(name: "Doggy", age; 3)
doggy.grow() // doggy는 Animal(name: "Doggy", age: 4)인 별개의 인스턴스로 대체
→ 단순히 doggy의 age가 4로 변하는 것이 아니라, Animal(name: "Doggy", age: 4)인 전혀 다른 별개의 인스턴스로 대체됨
💡doggy2.age = 4에서는 인스턴스 대체가 일어나는가?첫 번째 예시 코드에서는 메소드가 아닌
doggy2.age = 4로 직접 속성을 변경하였다.이 경우에도 메소드와 동일하게 인스턴스가 대체되는 방식으로 작동하지만, 첫 번째 예시는 두 인스턴스
doggy와doggy2가 다르다는 것을 보여주기 위한 것으로 해당 설명을 생략하였다.
mutating 키워드는 대체되어도 괜찮다!라는 것을 컴파일러에게 알리는 역할!⇒ 메소드 앞에 mutating 키워드를 붙임으로써 해당 메소드가 self(메소드를 호출하고 있는 현재의 인스턴스)를 새로운 인스턴스로 대체 가능하다라고 컴파일러에게 허락함
mutating을 안쓸까?class Animal {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
var doggy = Animal(name: "Doggy", age: 3)
var doggy2 = doggy
doggy2.age = 4
print(doggy.age) // 4 출력
print(doggy2.age) // 4 출력
→ doggy가 할당된 doggy2는 doggy와 완전히 동일한 인스턴스를 가리키고 있음!
⇒ 그렇기 때문에 doggy2.age를 바꾸어도 doggy.age와 doggy2.age는 동일하게 변경된 값인 4를 출력
➡︎ var doggy2 = doggy는 Animal(name: "Doggy", age: 3) 인스턴스 자체를 할당하는 것이 아닌, 해당 인스턴스에 대한 참조를 할당하는 것이므로 두 변수 doggy와 doggy2가 가리키는 인스턴스는 동일
➡︎ 따라서, 애초에 mutating을 사용하는 조건 자체가 아니기때문에(어차피 동일한 인스턴스니까) mutating 없이 메소드를 작성함!