Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- collectionview
- 리펙토링
- RxCocoa
- ios
- Human interface guide
- 리펙터링
- clean architecture
- 스위프트
- 애니메이션
- map
- UICollectionView
- combine
- 리팩토링
- Observable
- MVVM
- SWIFT
- swiftUI
- Xcode
- ribs
- uitableview
- rxswift
- tableView
- Refactoring
- UITextView
- uiscrollview
- swift documentation
- Clean Code
- Protocol
- HIG
- 클린 코드
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift 공식 문서] 22. Generics (제네릭스) 본문
Generics
- 제네릭스를 사용하는 목적
- 유연하고 재사용 가능한 함수 작성
- 중복을 피하고 그 의도를 명확하고 추상적인 방식으로 표현하는 코드 작성
Generics으로 해결할 수 있는 문제
- swap 함수
// non-generics
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
// generics
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
generics를 사용하여 linked-list 구현
- Node 정의
public class Node<T> {
var value: T
var next: Node?
weak var previous: Node? // weak가 아니면 순한참조 발생
public init(value: T) {
self.value = value
}
}
- Linked List 클래스 정의
public class LinkedList<T> {
private var head: Head?
public var isEmpty: Bool {
return head == nil
}
public var first: Node? {
return head
}
public var last: Node? {
guard var node = head else {
return nil
}
while let next = node.next {
node = next
}
return node
}
}
- append
public func append(value: T) {
let newNode = Node(value: value)
if let lastNode = last {
newNode.previous = lastNode
lastNode.next = newNode
} else {
head = newNode
}
}
- index로 노트 탐색
public func node(at index: Int) -> Node {
if index == 0 {
return head!
} else {
var node = head!.next
for _ in 1..<index {
node = node?.next
if node == nil {
break
}
}
return node!
}
}
- insert at index
public func insert(value: T, at index: Int) {
let newNode = Node(value: value)
if index == 0 {
newNode.next = head
head?.previous = newNode
head = newNode
} else {
let previousNode = self.node(at: index - 1)
let nextNode = previousNode.next
newNode.previous = previousNode
newNode.nextNode = previousNode.next
previousNode.next = newNode
nextNode?.previous = newNode
}
}
- remove at
public func remove(node: Node) -> T {
let previousNode = node.previous
let nextNode = node.next
if let previousNode = previousNode {
previousNode.next = nextNode
} else {
head = nextNode
}
nextNode?.previous = previousNode
node.previous = nil
node.next = nil
return node.value
}
public func removeAt(_ index: Int) -> T {
let nodeToRemove = node(at: index)
return remove(node: nodeToRemove)
}
Generics 제한 조건
- T와 U라는 Generics에 특정 조건 부여
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
// function body goes here
}
Associated Type
- protocol에서 제네릭과같은 개념
- protocol이 채택될때 유형이 지정
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
- associatedtype에 제약 추가
protocol Container {
associatedtype Item: Equatable
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
Generics에서의 where closure
- C1 타입은 Container 프로토콜을 준수: C1: Container
- C2 타입은 Container 프로토콜을 준수: C2: Container
- C1.Item과 C2.Item은 같은 타입: C1.Item == C2.Item
- C1I.tem은 Equatable 프로토콜을 준수: C1.Item: Equatable
func allItemsMatch<C1: Container, C2: Container>
(_ someContainer: C1, _ anotherContainer: C2) -> Bool
where C1.Item == C2.Item, C1.Item: Equatable {
// Check that both containers contain the same number of items.
if someContainer.count != anotherContainer.count {
return false
}
// Check each pair of items to see if they're equivalent.
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// All items match, so return true.
return true
}
Extension으로 Generics + where
extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {
guard let topItem = items.last else {
return false
}
return topItem == item
}
}
Context Where - method에서 작성
extension Container {
func average() -> Double where Item == Int {
var sum = 0.0
for index in 0..<count {
sum += Double(self[index])
}
return sum / Double(count)
}
func endsWith(_ item: Item) -> Bool where Item: Equatable {
return count >= 1 && self[count-1] == item
}
}
Subscript에서의 generics where
extension Container {
subscript<Indices: Sequence>(indices: Indices) -> [Item]
where Indices.Iterator.Element == Int {
var result: [Item] = []
for index in indices {
result.append(self[index])
}
return result
}
}
* 참고
https://docs.swift.org/swift-book/LanguageGuide/Generics.html
'swift 공식 문서' 카테고리의 다른 글
[iOS - swift 공식 문서] 24. ARC (Auto Reference Counting) (0) | 2021.07.24 |
---|---|
[iOS - swift 공식 문서] 23. Opaque result Type (불투명 반환 타입 some) (0) | 2021.07.23 |
[iOS - swift 공식 문서] 21. Protocols (프로토콜) (0) | 2021.07.20 |
[iOS - swift 공식 문서] 20. Extensions (확장) (0) | 2021.07.19 |
[iOS - swift 공식 문서] 19. Nested Type (중첩 타입) (0) | 2021.07.17 |
Comments