[Swift] SwiftUI로 느낀 Swift 기본기의 중요성
·
Swift/개념 & 응용
서론SwiftUI를 학습하면서 Swift 기본기의 중요성을 크게 느꼈습니다.SwiftUI는 구현이 매우 편리하지만, 학습 과정은 그만큼 쉽지 않다고 생각합니다.이번 포스팅에서는 View 프로토콜을 Swift 기반으로 단계적으로 이해해 나갔던 제 학습 과정을 공유하고자 합니다. 1단계: View 프로토콜 정의가장 먼저 공식문서가 말하는 View 프로토콜을 봅시다.@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)public protocol View { associatedtype Body : View @ViewBuilder var body: Self.Body { get }}View 프로토콜은 body computed 프로퍼티를 가지는 타입입니다..
[Swift] flatMap이 deprecated가 된 이유 / compactMap의 등장
·
Swift/개념 & 응용
서론Swift 4.1에서 flatMap이 deprecated되고 compactMap으로 역할이 분리되었습니다.저는 한 가지 착각하고 있었습니다. "flatMap이 아예 사라지고 compactMap이 새로 생겼구나"라고 오해했는데요, flatMap은 여러 형태가 존재했고, flatMap 중 하나가 compactMap이 된거였습니다.이번 포스팅은 pointfree의 https://www.pointfree.co/episodes/ep10-a-tale-of-two-flat-maps 영상과 스크립트를 정리한 포스팅입니다. flatMap이 어떤 형태를 제공했었고, 어떤 메서드가 compactMap이 된 것인지 알아보겠습니다. flatMap의 세 가지 형태flatMap은 총 세 가지 형태로 제공됩니다.extension..
[Swift] DTO 매크로(Macros)로 CodingKeys 반복 패턴 제거하기
·
Swift/개념 & 응용
Swift Macros 사용 이유이전 포스팅(https://jeong9216.tistory.com/727)에서 Swift macros에 대해 소개했습니다.Swift macros는 코드 작성 시 발생하는 반복적인 패턴을 효과적으로 제거하는 데 큰 도움이 됩니다.여기서 주목할 점은 단순한 코드의 반복이 아닌, 코드만으로는 해결하기 어려운 '패턴의 반복'을 제거할 수 있다는 것입니다. 이는 Swift macros의 강력한 특징 중 하나입니다. 구체적인 예로, DTO(Data Transfer Object)에서 CodingKeys를 작성하는 패턴을 들 수 있습니다. 이러한 패턴은 일반적인 방법으로는 코드 레벨에서 반복을 제거하기 어렵습니다. 그러나 Swift macros를 활용하면 이러한 반복적인 패턴을 효과적으..
[Swift] difference(from:)와 applying(_:)
·
Swift/개념 & 응용
difference(from:) difference(from:)은 두 개의 Collection 차이를 쉽게 구할 수 있는 메서드입니다. A와 B를 비교했을 때 무엇이 추가로 있고, 무엇이 없는지 알 수 있습니다. (A collection of insertions and removals that describe the difference between two ordered collection states.) 사용법도 간단합니다. let arr1 = [1, 2, 3, 4] let arr2 = [1, 3, 4, 5] let diff = arr2.difference(from: arr1) diff를 출력해 보면 arr1이 arr2가 되기 위해 무엇을 추가하고, 무엇을 빼야 하는지 알 수 있습니다. "Collect..
[Swift] 프로토콜 메서드의 매개변수 기본 값 설정 (Defining default parameters for protocol methods)
·
Swift/개념 & 응용
서론 프로토콜 타입을 사용할 때 불편한 점이 하나 있습니다. 메서드 파라미터에 기본 값을 사용할 수 없다는 점입니다. 예를 들어, UseCase의 execute 파라미터로 page를 전달해야 한다고 합시다. protocol UseCaseProtocol { func execute(page: Int) } struct UseCase: UseCaseProtocol { func execute(page: Int) { // Logic } } let useCase: UseCaseProtocol = UseCase() useCase.execute(page: 1) 그러면 위 코드처럼 항상 page를 전달해줘야 해요. page에 기본 값을 설정하고 싶어도 프로토콜 메서드에는 Default argument를 설정할 수 없다는 ..
[Swift] NSCoding과 Codable 차이점 (상속 관계 유지하기)
·
Swift/개념 & 응용
NSCoding과 Codable Codable이 나오면서 NSCoding은 옛날의 그것으로 생각되었습니다. 그런데 NSCoding만이 할 수 있는 일이 있었습니다. 바로 상속 관계를 유지해서 저장하는 것입니다. Shape 부모 클래스를 상속하는 두 개의 자식 클래스가 있습니다. class Plane { var shapes: [Shape] init(shapes: [Shape]) { self.shapes = shapes } func display() { for shape in shapes { print("\(type(of: shape)): \(shape.description)") } } } let shapes: [Shape] = [ Rect(point: .init(x: 10, y: 10), size: .in..
[Swift] 구조체와 클래스의 Property Observer 동작 차이 (짧은글)
·
Swift/개념 & 응용
Property Observer Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value. Property Observer는 프로퍼티의 "값"이 변하면 호출됩니다. 여기서 "값"의 의미때문에 구조체와 클래스의 프로퍼티 옵저버 동작 차이가 발생합니다. struct StructA { var value: Int = 0 } class ClassA { var value: Int = 0 } var struc..
[Swift] OptionSet 알아보기
·
Swift/개념 & 응용
OptionSet OptionSet은 비트 마스크를 이용해 여러 옵션을 다룰 때 채택하는 프로토콜입니다. 프로토콜이지만 이름에 Set이 붙은 거처럼 분류도 Collections로 되어 있고, intersection, union 등 집합 메서드도 사용할 수 있습니다. (이건 아래에서 더 자세히 알아볼게요.) OptionSet이 낯설 수 있는데요. 생각보다 많은 곳에서 사용됩니다. 대표적으로 UIView.AnimationOptions, UIView.AutoresizingMask가 있습니다. OptionSet 사용법 struct ShippingOptions: OptionSet { let rawValue: Int static let nextDay = ShippingOptions(rawValue: 1
[Swift] Equatable의 Synthesized Conformance 분석
·
Swift/개념 & 응용
서론 구조체와 클래스의 프로토콜 자동 준수 메커니즘 (w. ChatGPT)에서 Synthesized Conformance를 가볍게 다뤘습니다. 이번 포스팅에서는 SIL, CPP 코드를 분석해 Equatable의 Synthesized Conformance가 진행되는 과정을 알아보겠습니다. Equatable Equatable은 == static 메서드를 준수해야 하는 프로토콜로 == 연산자의 좌변과 우변을 비교해서 같은지 확인해 주는 역할입니다. 그리고 Synthesized Conformance를 지원하는 프로토콜 중 하나죠. Equatable은 아래 상황에서 Synthesized Conformance를 지원합니다. 구조체가 Equatable을 준수하는 저장 프로퍼티만 가지고 있는 경우 열거형의 모든 케이스..
[Swift] 구조체와 클래스의 프로토콜 자동 준수 메커니즘 (w. ChatGPT)
·
Swift/개념 & 응용
서론 최근 Equatable, Hashable, Comparable을 복습하면서 궁금한 점이 있었습니다. 왜 구조체는 채택만 해도 자동으로 준수가 되는데 클래스는 직접 요구 메서드를 구현해야 하는 걸까?입니다. Value 타입과 Reference 타입의 차이와 연관이 있다는 건 추측할 수 있었지만, 명확한 이유를 찾긴 어려웠습니다. 그래서 이번에는 ChatGPT와 함께 문제를 해결해 보았습니다. 스텝 바이 스텝으로 대답이 정확해지는 과정이 재밌어서 이렇게 포스팅으로 남겨봅니다. 1. 일단 질문하기 일단 큰 고민 없이 물어봤습니다. 그럴듯한 대답이 나왔습니다만, "값 타입이 프로토콜을 채택만 해도 되는 이유"에 대한 답은 아니었습니다. 2. 클래스와 비교하여 질문 다음은 클래스와 비교해서 질문했습니다. 이..
[Swift] Optional.swift 살펴보기
·
Swift/개념 & 응용
Optional.swift를 살펴보게 된 계기 옵셔널은 Swift의 장점 중 하나입니다. 백준 문제를 풀다가 문득 nil 병합 연산자(??)에 대해 궁금해졌습니다. 일반적인 연산자는 즉시 연산이 완료되는데, ?? 연산자는 앞의 수행 결과가 nil인 경우 실행이 되는 부분이 흥미로웠어요. 어떻게 구현되었길래 지연 실행이 되는거지? 라는 생각이 들었습니다. 많은 블로그에서 이미 다룬 주제지만, 실제 구현 코드가 궁금해서 Optional.swift를 살펴봤는데요. 보기 전에는 너무 어려워서 못 읽을 줄 알았지만 막상 보니 읽을만 한거에요..? 그래서 한 번 쫙 읽고 포스팅으로 정리까지 하게 되었습니다 ㅋㅋ 전부 다루는건 아니기 때문에 Optional.swift와 함께 보시면 좋습니다. 기본 구조 @frozen..
[Swift] Generic, Protocol을 이용한 Extension Wrapping
·
Swift/개념 & 응용
Extension Wrapping Extension Wrapping은 유명 라이브러리에서 자주 보이는 구조입니다. (참고로 Extension Wrapping은 정식 명칭이 아니라 제가 임의로 정한 이름입니다.) 대표적으로 Kingfisher, RxSwift가 있습니다. imageView.kf.setImage(with: url) Kingfisher 메서드를 사용할 때 UIImageView가 아니라 kf를 이용해 메서드를 호출하죠? 바로 그게 Extension Wrapping입니다. Extension으로 구현한 Kingfisher 메서드를 UIView에서 직접 호출하지 않고, KingfisherWrapper로 호출하는 것입니다. Extension Wrapping 장점 Extension Wrapping은 안정..
[Swift] Failable Initializer (실패 가능한 초기화)
·
Swift/개념 & 응용
Failable Initializer Failable 초기화는 실패가 가능한 초기화입니다. 클래스, 구조체, 열거형에서 실패 가능한 초기화를 정의할 수 있습니다. Failable 초기화 예시 실패가 가능한 초기화는 특정 조건에서만 객체가 생성되어야 할 때 유용합니다. class Time { var hour: Int var minute: Int } 예를 들어, Time 클래스는 hour와 minute 변수가 있습니다. hour의 범위는 1~12여야 하고, minute은 0~59여야 합니다. 이외의 숫자가 들어오면 객체가 생성되지 않도록 하고 싶을 때 Failable 초기화를 사용할 수 있습니다. class Time { var hour: Int var minute: Int init?(hour: Int, mi..
[Swift] memberwise 초기화, convenience 초기화
·
Swift/개념 & 응용
서론 Swift에서 구조체와 클래스는 많은 차이가 있고, 초기화도 그중 하나입니다. 구조체는 멤버와이즈(memberwise) 초기화를, 클래스는 편의(convenience) 초기화를 가지고 있죠. 초기화에 대해 할 말은 굉장히 많지만, 이번 포스팅에서는 멤버와이즈(memberwise) 초기화와 convenience 초기화에 집중해서 알아보겠습니다. 초기화(Initializer) 초기화란 구조체, 열거형, 클래스의 인스턴스를 생성하는 것입니다. 초기화의 역할은 모든 프로퍼티를 기본값으로 초기화하는 것입니다. 만약 초기화가 끝나는 시점에 모든 프로퍼티가 기본값을 가지고 있지 않다면 초기화가 실패됩니다. (여기서 언급한 초기화의 역할은 아래에서도 꾸준히 언급되므로 알아두시면 좋겠습니다.) Default Ini..
[Swift] 꼬리 재귀(Tail Recursion)와 꼬리 재귀 최적화
·
Swift/개념 & 응용
꼬리 재귀(Tail Recursion) 꼬리 재귀란 재귀의 결과를 바로 반환하는 재귀 형태입니다. 말로 들으면 무슨 말인가 이해가 안 될 것이므로 코드로 알아보겠습니다. 아래 함수들은 단순히 1 ~ n까지의 합을 구하는 역할입니다. 먼저 일반 재귀 형태를 먼저 보겠습니다. func recursion(_ num: Int) -> Int { if num == 0 { return num } return num + recursion(num - 1) } 파라미터로 num을 전달 받고 num + recursion 결과를 반환합니다. 이 메서드 안에는 num + recursion 이라는 연산이 존재합니다. 연산이 존재하면 연산을 위한 값을 스택에 저장해야하기 때문에 재귀를 할 때마다 스택에 메모리 할당이 발생합니다. ..
유정주
'Swift/개념 & 응용' 카테고리의 글 목록