제일 중요함!!
struct StructClassActorBootcamp: View {
var body: some View {
Text("Hello, World!")
.onAppear {
runTest()
}
}
}
struct MyStruct {
let title: String
}
extension StructClassActorBootcamp {
private func runTest() {
print("Test started!")
}
private func structTest1() {
let objectA = MyStruct(title: "Starting title!")
print("ObjectA: ", objectA.title)
let objectB = objectA
print("ObjectB:", objectB.title)
objectB.title = "Second title!"
}
}
요렇게 구성이 되어 있다고 생각해봅시다
objectA 를 그대로 objectB에 넣어주고,
ojbectB의 title을 변경하려하면 에러가 발생하죠
MyStruct에 있는 프로퍼티를 let으로 선언했기 때문에
var로 바꿔줘야한다~고 이야기합니다
두번째 에러는 let 으로 선언했던 objectB를 var로 바꿔야한다고 이야기하고 있고!
이번엔 클래스로 해볼까요?
바로 전에 했던 struct처럼 에러가 뜨죠?
근데 fix를 누르면 struct를 할 때처럼 objectB를 변수로 바꾸는 게 아니라, class내의 프로퍼티 자체를 var로 바꿔주고
메소드 내의 objectB는 let으로 선언되도 에러가 안 뜨는 걸 볼 수 있음
class는 참조타입이고 그 객체의 주소값을 바라보고 있어서 그렇겠죠!
그럼 값타입과 참조타입을 어떤 때에 사용해야하는가?
참조 타입은 매번 싱크를 맞춰주게 되니까
값타입에 비해서는 메모리를 더 먹음
어떻게 메모리에 저장되는지는 조금 이따 알아볼거고
먼저 struct와 class 업데이트하는 걸 해봅시다
structTest2()를 만들었는데 struct1을 let으로 선언하면 에러가 뜸
var로 바꿔주고
struct2 처럼 업데이트 하면 값타입의 struct를 매번 만들어줘야하잖음
아~
이렇게 해줬던 게 비기너들이 첨에 이해하기 쉬워서 그런거였구나
struct의 프로퍼티를 struct내에서 바꿔주려고 하면
첫번째로 title 바꿔주라는 에러가 뜨고
function에 mutating 키워드를 붙이라고함
이렇게 하면 title을 바꾸게 되면 오브젝트 자체가 변경되게 됨
struct4를 이제 그냥 update해줄 수 있게됐죠!
struct MyStruct {
var title: String
}
/// Immutable struct
struct CustomStruct {
let title: String
func updateTitle(newTitle: String) -> CustomStruct {
CustomStruct(title: newTitle)
}
}
struct MutatingStruct {
var title: String
mutating func updateTitle(newTitle: String) {
title = newTitle
}
}
이렇게 3개의 차이가 뭔지 알겠나?!
struct 를 업데이트하는 것에 제한을 주는 것을 좋아하면 Mutating 쓰셈
첫번째처럼 그냥 쓰는 것도 솔직히 상관은 없음
코드 깔끔하잖음
Mutating 쓸 때 private으로 해주고 (set)만 가능하게 하는거임
내부에서는 수정이 가능하지만 외부에서는 수정이 불가능하게!!
struct내의 프로퍼티를 var 로 선언할지 let으로 선언할지는
의견들이 다양한가봄 찾아보자
제일 처음 배울 때 헷갈렸던 거
class 같은 경우에 let으로 선언됐는데도 안의 프로퍼티들을 바꾸는게 가능함..!
class MyClass {
var title: String
init(title: String) {
self.title = title
}
func updateTitle(newTitle: String) {
title = newTitle
}
}
이번에도 update메소드를 만들어봅시다
class엔 mutating을 붙일 수 없다고 하죠
그냥 update가 가능합니다
기본적인 값 타입들은 stack에 저장된다!
값타입을 복사해서 넘기는 게 여러개의 레퍼런스를 하는 것보다
효율적임!
싱크를 일일이 안 맞춰줘도 되니까!
iOS어플 개발하다보면 여러개의 Thread를 관리하게 되는 걸 볼 수 있음
Automatic Reference Counting
Value 타입은 ARC의 영향을 받지 않음
Class vs Actor
클래스랑 비슷하면서 다름
Actor는 Thread safe 함
예를들어서 멀티스레드 환경에서
힙에 저장된 어떤 오브젝트를 여러개의 스레드에서 참조하고 있었다고 해보셈
그럼 만약에 이 태스크들이 동시에 요청이 되면
멘붕하잖음
다 같은 애를 바라보고 있으니까
그럴 때 Actor라는 키워드를 붙이면 await를 해주게 됨
코드로 확인해봅시다
MyActor라는 actor를 만들어줬다
그리고 메소드에서 이 actor 인스턴스를 만들어주면
에러가 뜨는 걸 볼 수 있음
메소드에 async를 붙이거나
Task { } 안에 넣어줘야합니다
Task 안에 넣어주고 나면 객체에 접근하려고 할 때마다
await키워드를 붙여줘야함!
await 다붙여주고나면 외부에서 actor를 수정할 수 없다는 에러가 나옴!
그럼 내부에서 해주면 되겠죠?
-> struct에서 update해주던 느낌으로!!
private func actorTest1() {
Task {
print("classTest1")
let objectA = MyActor(title: "Starting title!")
await print("ObjectA: ", objectA.title)
print("Pass the REFERENCE of objectA to objectB.")
let objectB = objectA
await print("ObjectB: ", objectB.title)
await objectB.updateTitle(newTitle: "Second title! ")
print("ObjectB title changed.")
await print("ObjectA: ", objectA.title)
await print("ObjectB: ", objectB.title)
}
}
이렇게!!
actor도 class도 참조
힙에 저장됨
actor는 참조 형태가 비동기로 실행될 경우에 order를 잘 해줘서
thread safe하게 작업을 실행해주는 느낌
View init할 때랑
ViewModel init할 때 print 찍어보면
view는 매번 프린트가 찍히는데
ViewModel은 젤 처음 init될 때만 찍힘
VALUE TYPES:
- Struct, Enum, String, Int, etc.
- stored in the Stack
- Faster
- Thread safe!
- When you assign or pass value type a new copy of data is created
REFERENCY TYPES:
- Class, Function, Actor
- Stored in the Heap
- Slower, but synchronized
- Not Thread safe (by default)
- When you assign or pass reference type a new reference to original instance will be created (pointer)
--------------------
Stack:
- Stores Value types
- Variables allocated on the stack are stored directly to the memory, and access to this memory is very fast
- Each thread has it's own stack!
HEAP:
- Stores Reference types
- Shared across threads!
____________________
STRUCT:
- Based on VALUES
- Can be mutated
- Stored in the Stack!
CLASS:
- Based on REFERENCES (INSTANCES)
- Stored in the Heap!
- Inherit from other classes // It's common interview question but in swiftUI Do we really use this?
ACTOR:
- Same as Class, but thread safe!
_____________________
Structs: Data Models, Views
Classes: ViewModels
Actors: Shared 'Manager' and 'Data store'