본문 바로가기

스위프트18

ARC 2편 - 강한 참조 순환 클래스 인스턴스간 강한 참조 순환 (Strong Reference Cycles Between Class Instances) 클래스의 인스턴스 간 강하게 상호 참조를 하고 있는 경우에는 ARC에서 자동으로 메모리 해제를 못하는 경우도 있다. Person 클래스와 Apartment 클래스가 있다. Person 클래스 내의 apartment 저장 프로퍼티 경우는 Apartment 클래스 타입을 따르고 있고, Apartment 클래스 내의 tenant 저장 프로퍼티 경우는 Person 클래스 타입을 따르고 있다. class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print.. 2024. 4. 19.
ARC 1편 - ARC 란? ⭐ 참조타입은 메모리 해제가 중요한 문제이다. 왜냐하면? 인스턴스가 적절한 시점에 메모리에서 해제되지 않으면 메모리 자원 낭비 + 성능 저하로 이어지기 때문이다. 이를 해결하고자 스위프트에서는 메모리 관리 기법인 ARC를 사용한다. ✔ RC: Reference Counting 으로 참조 횟수 계산을 뜻한다. (구조체, 열거형은 값 타입으로 적용이 안된다.) ARC 사용 Person 클래스를 선언하고, init(), deinit을 통해 인스턴스 생성과 해제에 따른 print()문을 실행한다. class Person { let name: String init(name: String) { self.name = name print("\(name) is being initialized") } deinit { pr.. 2024. 4. 19.
접근 제어자 (Access Control) 코드에서 상호작용을 할 때 소스 파일 간 또는 모듈 간 접근을 제한할 수 있는 기능을 말한다. ⭐특정 코드의 세부적인 구현을 숨기거나, 허용된 기능만 사용하는 인터페이스를 제공할 수 있다.⭐ ✅ 모듈: 배포할 코드의 묶음 단위로 "import" 를 통해 불러오는 것을 말한다. ✅ 소스파일: Swift 코드 파일 1개를 의미한다. ✅ 파일 간 또는 모듈 간에 접근 제한하는 목적은 "은닉화"에 있다. 접근 레벨의 종류 open - 개방 접근수준 가장 넓은 범위 지정된 요소는 어디서든 사용 가능하다. Open은 클래스에만 사용 가능하다. Open에서만 클래스가 정의된 모듈 외부에서도 subclassing할 수 있다. Open에서만 클래스가 정의된 모듈 외부에서 override 할 수 있다. public - 공.. 2024. 4. 17.
서브스크립트 클래스, 구조체, 열거형에서 시퀀스의 멤버 요소에 접근하기 위한 바로가기 첨자로, 단일 타입에 여러 서브스크립트를 정의할 때 사용한다. 배열을 사용하면서 배열 내의 element에 접근할 때 사용한다. let nums: [Int] = [1, 2, 3, 4] nums[0] // 1 nums[1] // 2 " [ ] " 대괄호 안에 index를 통해 배열 내의 element에 접근하는데 이게 바로 서브스크립트이다. 서브스크립트 정의문법 서브스크립트 정의 문법은 연산 프로퍼티와 비슷하다. getter / setter 모두 구현 가능하고, get only는 되지만, set only는 불가능하다. subscript(index: Int) -> Int { get { } set(newValue) { } } String.. 2024. 4. 16.
제네릭 (제네릭 제약, 제네릭 확장, 제네릭 함수와 오버로딩) 타입 제약 제네릭 함수와 타입을 사용할 때, 특정 클래스의 하위 클래스나 특정 프로토콜을 준수하는 타입만 받을 수 있게 제약할 수 있다. 프로토콜 제약 두 개의 값을 파라미터로 받을 때, 값이 같으면 true 또는 값이 다르면 false를 반환하는 함수를 제네릭으로 선언한다면? func isSameValues(_ a: T, _ b: T) -> Bool { return a == b // Binary operator '==' cannot be applied to two 'T' operands } 에러가 발생한다. 이유는, " == " 이라는 연산자는 a와 b의 타입이 Equatable 이라는 프로토콜을 준수할 경우에만 사용할 수 있기 때문이다. 따라서 아래와 같이 타입 파라미터가 " Equatable " 프.. 2024. 4. 16.
고차함수 다른 함수를 전달인자로 받거나 함수실행의 결과를 함수로 변환하는 함수이다. 스위프트에서 함수(클로저)는 일급 시민이기 때문에 함수의 전달인자로 전달할 수 있고, 함수의 결과값으로 반환할 수 있다. map 컨테이너 내부의 기존 데이터를 변형하여 새로운 컨테이너를 생성한다. 1️⃣ 변형하고자 하는 numbers / 변형 결과를 받을 doubledNumbers, strings let numbers: [Int] = [0, 1, 2, 3, 4] var doubledNumbers: [Int] = [] var strings: [String] = [] 2️⃣ 기존의 for 구문 사용 for number in numbers { doubledNumbers.append(number * 2) strings.append("\(.. 2024. 4. 15.
오류처리 스위프트에서 오류(Error)는 Error라는 프로토콜을 준수하는 타입의 값을 통해 표현된다. ⭐️ Error 프로토콜은 사실상 요구사항이 없는 빈 프로토콜이다. ⭐️ 오류를 표현하기 위한 타입 (주로 열거형)은 이 프로토콜을 채택한다. 오류표현 Error 프로토콜과 열거형을 통해 오류를 표현한다. enum 오류종류이름: Error { case 종류1 case 종류2 case 종류3 //... } ⭐ HTTP 상태 코드를 참고하여 만든 예시 오류 enum HttpError: Error { case badRequest case unauthorized case forbidden case notFound case requestTimeOut case conflict } 함수에서 발생한 오류 던지기 자판기 동작 .. 2024. 4. 13.
익스텐션 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있는 기능이다. 타입만 알고 있다면, 그 타입의 소스 코드를 모르더라도 기능을 확장할 수 있다. ⭐️ 익스텐션은 타입에 새로운 기능은 추가할 수 있지만, 기존에 존재하는 기능을 재정의할 수 없다. 익스텐션을 사용하는 대신에 원래 타입을 정의한 곳에서 추가하는 방법도 있지만, 외부 라이브러리나 프레임워크를 가져다 쓴다면 수정하지 못한다. 외부에서 가져온 타입에 내가 원하는 기능을 추가하고자 할 때 익스텐션을 사용한다. 익스텐션 구현 연산 프로퍼티 추가 extension Int { var isEven: Bool { return self % 2 == 0 } var isOdd: Bool { return self % 2 == 1 } } print.. 2024. 4. 12.
Result Type (리절트 타입) 스위프트5에서 새롭게 추가된 Result Type은 에러 처리할 때 사용한다. 에러가 발생하는 경우 리턴 타입 자체를 Result Type으로 구현해서 함수 실행의 성공과 실패의 정보를 담아서 반환한다. ▶️ 기존의 에러 처리인 경우, 성공과 실패에 대한 결과를 따로 처리하고 do catch 블럭으로 감싸야 한다. 에러정의 enum MyError: ErrorType { case someError case criticalError } throws를 활용한 에러처리 func doSomething() throws { throw MyError.someError } do { try doSomething() } catch let myError as MyError { switch myError { case .some.. 2024. 4. 12.
프로토콜 프로토콜은 특정 역할을 수행하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진을 정의한다. 구조체, 클래스, 열거형은 프로토콜을 채택해서 특정 기능을 수행하기 위한 프로토콜의 요구사항을 구현할 수 있다. 어떤 프로토콜의 요구사항을 모두 따르는 타입은 해당 프로토콜을 준수한다라고 표현한다. 타입에서 프로토콜의 요구사항을 충족시키려면 프로토콜이 제시하는 청사진의 기능을 모두 구현해야 한다. ⭐️ 프로토콜은 기능을 정의하고 제시할 뿐, 스스로 기능을 구현하지 않는다. 정의문법 protocol 프로토콜 이름 { /* 정의부 */ } 프로토콜의 요구는 항상 "var" 키워드를 사용한다. get은 읽기만 가능, get + set을 모두 명시하면 읽기 + 쓰기 모두 가능하다는 뜻이다. 프로토콜 구현 protoc.. 2024. 4. 11.
assert와 guard 애플리케이션이 동작 도중에 생성하는 다양한 연산 결과값을 동적으로 확인하고 안전하게 처리할 수 있도록 확인 및 처리할 수 있다. Assertion assert 함수는 디버깅 모드에서만 동작 배포하는 애플리케이션에서는 제외된다. 주로 디버깅 중 조건의 검증을 위하여 사용한다. 조건이 맞지 않으면 동작을 중지하면서 에러 표시에 메시지가 나온다. 나이를 확인하고 에러 발생하면 디버깅 창에서 에러창이 보이게 하는 함수를 생성한다면? 빠른 종료 "guard"를 사용하여 잘못한 값의 전달 시 특정 실행구문을 빠르게 종료한다. "guard"의 "else" 블럭 내부에는 특정 코드 블럭을 종료하는 지시어 (return, break 등)가 꼭 있어야 한다. 타입 캐스팅, 옵셔널과도 자주 사용된다. func functio.. 2024. 4. 9.
옵셔널 체이닝 옵셔널 체이닝 옵셔널의 내부의 내부의 내부로 옵셔널이 연결되어 있을 떄 활용할 수 있다. 매 번 nil 확인을 하지 않고 최종적으로 원하는 값이 있는지 없는지 확인할 수 있다. Person 클래스의 home 이라는 프로퍼티는 Apartment 클래스 타입을 사용한다. Apartment 클래스의 guard, owner 프로퍼티는 Person 클래스 타입을 사용한다. class Person { var name: String var job: String? var home: Apartment? init(name: String) { self.name = name } } class Apartment { var buildingNumber: String var roomNumber: String var `guard`: .. 2024. 4. 6.