728x90
스위프트 표준 라이브러리 활용
- 표준 라이브러리의 개념은 무척 넓고 다양하다
- 라이브러리에서 정의한 다양한 프로토콜을 적용할 수 있는 버용 구조체와 열거형을 통해 다양한 기능 제공
- Array.append() 함수 예시
- 해당 배열의 저장 내용을 다른 뱅려과 실시간으로 공유하지 않을 경우 알고리즘의 복잡성 $O(1)$만큼 커짐
- 함수 실행을 위해 해당 배열을 브릿징한 NSArray로 래핑해야 하며, 그렇지 않을 경우 알고리즘의 효율성은 매우 낮아짐
애플이 구조체를 사용하는 이유
- 객체지향형 언어를 이용해서 프로그래밍을 했다면, 원하는 타입을 만들기 위해 클래스라는 구조 또는 개념을 사용해 왔을 것 하지만 스위프트 표준 라이브러리에서는 이와 같은 용도로 클래스를 사용하지 않음
- 스위프트에 정의된 타입 대부분은 구조체
- 스위프트는 왜 밸류 타입인 구조체를 써서 레퍼런스 타입인 클래스를 지원한 이유
- 상속, 초기화 해제객체, 레퍼런스 카운팅등 다양한 기능을 제공하는 클래스에 비해 훨씬 제한된 기능을 제공하는 스위프트가 표준 라이브러리의 구성 요소로 적합
- 구조체는 Value Type이며, 단 하나의 소유 객체만을 지님, 새로운 변수에 할당하거나 함수에 전달할 때 항상 복사해서 사용한다는 것도 중요한 이유
- 구조체의 단순성은 코드를 체계적으로 안정화, 특정 구조체를 변경해도 애플리케이션의 다른 부분은 이에 영향을 받지 않음
스위프트 구조체의 주요기능
- 자동으로 생성되는 멤버 초기화 함수(memberwise initializer)외에 커스텀 초기화 함수도 사용 가능
- 메소드를 지낼 수 있음
- 프로토콜을 구현할 수 있음
클래스보다 구조체를 사용할 때
- 특정 타입 생성의 가장 중요한 목적이 간단한 몇 개의 캡슐화하려는 것인 경우
- 캡슐화한 값을 구조체의 인스턴에 전달하거나 할당할 때 참조가 아닌 복사를 할 경우
- 구조체에 의해 저장되는 프로퍼티를 참조가 아닌 복사를 위한 밸류타입인 경우
- 기존의 타입에서 가져온 프로퍼티나 각종 기능을 상속할 필요가 없는 경우
Choosing Between Structures and Classes | Apple Developer Documentation
스위프트에서 배열 선언
- 배열은 순위 목록에 동일 타입의 값을 저장하는 데이터 타입
- 동일타입의 값만 저장해야 함
- 하지만 상이한 타입의 값을 사용할 경우, 프로토콜의 배열로 정의해서 다양한 타입을 받아들이거나 AnyObject 타입의 배열로 정의할 수 있다.
- 제너릭 타입의 컬렉션, 어떤 타입이든 될 수 있음(int, floadt, string, class)
- 구조체로 정의 됨
- 모든 Array 클래스는 배열에 포함된 배열 요소를 저장하기 위한 메모리 공간을 유지
- 배열 요소의 타입이 클래스 또는 @objc 프로토콜 타입이 아닌 경우, 배열의 메모리 영역은 인접 블록에 저장 클래스 또는 @objc 프로토콜 타입일 경우, 인접 블록에 NSArray의 인스턴스에 저장
- 스위프트 배열은 기하급수적 증가 전략을 따르며, 배열에 요소가 추가될 때마다 소진된 배열 용량을 자동으로 증가
- 배열 요소 추가 작업을 여러 차례 나눠서 반복적으로 진행할 경우, 각각의 추가 작업에는 일정한 시간이 소요 됨
- 배열에 대량의 요소가 추가 될 것임을 알 경우,추가적인 배열 용량을 미리 할당 추가될 때마다 배열이 스스로 저장 공간을 할당하는 데 드는 시간을 줄일 수 있다.
var largeArray = [Int]()
// 배열에 대량의 요소 추가 전에 용량 미리 예약
let expectedCapacity = 1000
largeArray.reserveCapacity(expectedCapacity)
// 대량의 요소 추가
for i in 0..<expectedCapacity {
largeArray.append(i)
}
// 배열의 용량 확인
print("Actual Capacity: \\(largeArray.capacity)")
// 예상된 용량 이상의 실제 용량이 할당될 수 있음
- 배열을 복사할 경우, 저장공간이 할당되는동안에는 물리적으로 구분되는 별도의 복사물이 만들어지지 않음. 카피온라인트 기능, 하나 이상의 배열 인스턴스가 동일한 버퍼를 공유하는 변환작업이 완료될때까지 배열요소가 복사되지 않음
배열 초기화
- 구조체, 클래스, 열거형의 초기화 작업을 위해 init 메소드를 사용
- 스위프트 표준 라이브러리는 세 가지 타입의 배열을 구현하기 위해 네가지 초기화 메소드를 제공
// 배열 생성을 위한 정식 표현 문법
var intArray = Array<Int>()
// 배열 생성을 위한 단축 표현 문법
intArray = [Int](arrayLiteral: 0)
// 배열 리터럴 선언 방식
var intLiteralArray: [Int] = [1, 2, 3]
intLiteralArray = [Int](repeating: 2, count: 5)
배열에 요소 추가 및 업데이트
- .append()를 사용
- 기존 컬렉션 타입이 있을 때도 사용가능
딕셔너리 가져오기 및 초기화 하기
- 딕셔너리는 동일한 데이터 타입이 키와 값 쌍으로 묶여 있는 무순위 컬렉션
- 각각의 값은 딕셔너리 내에서 해당 값의 이름표와 같은 역할을 하는 키와 연결
- 키/값의 데이터 타입을 추측하므로 불필요한 코드 입력 줄임
// Dictionary 정식 문법
var myDict = Dictionary<Int, String>()
// Dictionary 단축 문법
var myDict1 = [Int:String]()
// 명시적인 딕셔너리 선언
var myDict3: [Int:String] = [1:"one"]
// 축약 딕셔너리 선언
var myDict4 = [1:"one"]
키/갑 쌍 추가, 변경, 삭제
- 새로운 키/값 쌍을 추가하거나 기존의 쌍을 업데이트 하려고 할 경우 .updateValue(_:forkey) 사용
// 딕셔너리에 새로운 쌍 추가
myDict.updateValue ("Four", forKey: 4)
// [2: "Two", 3: "Three", 1: "One", 4: "Four"]
// 서브스크립트 문법으로 새로운 쌍 추가하기
myDict[5] = "Five"
// [5: "Five", 2: "Two", 3: "Three", 1: "One", 4: "Four"]
- 키/값 쌍을 삭제하려면 removeValue(forKey:) 메소드에서 삭제하려는 값의 키를 입력
// 딕셔너리에서 키/값 쌍 삭제하고 삭제된 쌍 반환하기
let removedPair = myDict.removeValue(forKey: 1)
// [5: "Five", 2: "Two", 3: "Three", 4: "Four"]
// 서브스크립트로 딕셔너리에서 키/값 쌍 삭제하기
myDict [2] = nil
// [5: "Five", 3: "Three", 4: "Four"]
딕셔너리에서 값 가져오기
- 서브스크립트 문법을 이용해 딕셔너리 내에서 특정 키/값 쌍을 가져올 수 있음
- 서브스크립트의 대괄호 속에서 넣어서 전달하는데, 해당 키가 딕셔너리 상태에 존재하지 않을경우 옵셔널을 반환
- 옵셔널 바인딩 또는 강제 언래핑을 통해 해당 키/값 쌍을 가져오거나 해당 키/값 쌍이 없닥고 결론 지을 수 있음
// 옵셔널 바인딩의 사례
var myDict5 = [1: "One", 2: "Two", 3: "Three"]
if let optResult = myDict5[4] {
print (optResult)
} else {
print ("Key Not Found")
}
// 강제 언래평의 사례 - 이때는 해당 키가 반드시 존재해야 함
let result = myDict5[3]!
print (result)
- 반복적으로 순회하며 명시적으로 키와 값을 분할해서 사용할 수 있는 (key, value)튜플을 반환하도록 할 수 있다
// 미국 주의 약자와 주 명칭으로 구성된 딕셔너리
let states = [ "AL" : "Alabama", "CA" : "California", "A" : "Alaska",
"AZ" : "Arizona", "AR" : "Arkansas"]
for (stateÄbbr, stateName) in states {
print ("The state abbreviation for \\(stateName) is \\(stateÄbbr) ")
}
- 딕셔너리에서 키 또는 값만 개별적으로 가져오고 싶다면, keys 프로퍼티 또는 values 프로퍼티를 사용
- 이들 프로퍼티는 컬렉션에 대응하는 LazyMapCollection 인스턴스를 반환
- 반환된 딕셔너리 요소는 기본 요소에 포함된 변환 클로저 함수의 호출에 의해 정보를 읽을 때마다 지연 처리, 이때 키와 값은 각각.0멤버 .1멤버가되어 딕셔너리의 키값 쌍과 동일한 순서대로 나타냄.
for (stateAbbr) in states.keys {
print("State abbreviation: \\(stateAbbr)")
}
for (stateName) in states.values {
print("Stata Name : \\(stateName)")
}
- 딕셔너리는 기본적으로 무순위 컬렉션이지만, 가끔은 딕셔너리를 순회하면서 순위 목록을 정돈해야할 경우
- 전역 메소드인 sort(_:)를 이용, 딕셔너리 요소를 배열 요소처럼 정렬한 후 해당 배열을 반환
// 키의 값을 기준으로 딕셔너리를 정렬
let sortedArrayFromDictionary = states.sorted(by: { $0 < $1 })
// sortedArrayEromDictionary에 포함된 내용
// [("AK", "Alaska"), ("AI", "Alabana"), ("AR", "Arkansas"),
// ("AZ", "Arizona"), ("CA", "California") ]
for (key) in sortedArrayFromDictionary.map({$0.0}) {
print ("The key: \\(key) ")
}
for (value) in sortedArrayFromDictionary.map({$0.1}) {
print ("The value: \\(value) ")
}
728x90
'SwiftUI > 정리' 카테고리의 다른 글
[SwiftUI] TCA(The Composable Architecture)이란? (0) | 2024.03.18 |
---|---|
[SwiftDataStructure&Algorithms] 기본 데이터 구조(세트, 튜플) (0) | 2024.03.15 |
[SwiftDataStructure&Algorithms] 데이터 구조 (1) | 2024.03.12 |
XCODE IOS 프로파일링 디버깅 하는 방법 (1) | 2024.01.07 |
[SwiftUI] 아키텍처 고민 (0) | 2024.01.06 |