본문 바로가기

학습 노트/iOS (2021)

(96)
198. Concurrency with Context Concurrency with Context 대부분의 경우 하나의 Context로도 부족함이 없지만, 처리량이 많아지는 경우 Background Context를 활용한 동시처리(Concurrency)가 요구될 수 있다. MainQueueConcurrencyType과 PrivateQueueConcurrencyType으로 구분되며, 각각 Main Thread와 Background Thread에서 작동한다. Concurrency Context를 구현할때의 주의점은 다음과 같다. Context는 Thread에 안전하지 않다. Context에서 일어나는 모든 작업은 Context를 생성한 Thread에서 진행하고, 완료해야 한다. 다른 Context로 ManagedObject를 전달할 수 없다. 구조적으로 불가능..
197. Batch Processing with CoreData Batch Processing with CoreData CoreData에 저장하기 위해서는 Context를 생성하고, save 메서드를 호출해 context의 내용을 CoreData에 반영하는 방법으로 저장해야 한다. CoreData의 내용을 변경하기 위해서도 Context를 생성하고, CoreData의 내용을 Context에 불러온 뒤, 변경된 Context의 내용을 다시 CoreData에 반영해야 한다. 문제는 이러한 방식이 많은 양의 데이터를 처리할 수록 처리 시간과 사용하는 자원의 소모가 커진다는 데 있다. CoreData는 이러한 문제를 해결하기 위해 BatchUpdate와 BatchDelete를 제공한다. 이 기능들은 Context를 거치지 않고, 변경사항을 직접 CoreData에 반영함으로써..
196. Data Validation Data Validation Core Data에 CRUD 되는 상황에서 데이터의 무결성을 유지하기 위해 저장이나 업데이트를 시도하는 데이터의 종류나 형식에 제약을 걸 수 있다. Data Model에서 Inspector를 사용해 간단하게 검증 방식을 설정하고, NSManagedObject를 사용해 검증코드를 구현하는 방식으로 구현한다. Data Model에 검증방식 설정하기 xcdatamodeld > Person Entity > name Attribute Optional 해당 Attribute에 nil을 저장할 수 있도록 하는 속성이다. 비활성화하면 false에 해당하고 nil을 저장할 수 있고, 활성화하면 true에 해당하고 필수 nil을 저장할 수 없어 반드시 입력값이 존재해야 하는 필수 Attribu..
195. Faulting & Uniquing Faulting iOS 앱에서 DB를 사용하는 경우, 모든 경우에 저장소에 접근해 DB를 CRUD 하는 것이 아니라 Context에 불러 온 뒤 CRUD를 마치고 저장소를 업데이트 하는 방식을 사용한다. 이를 더 세분화 하면 Context에는 데이터 자체가 전달 되는 것이 아닌 정보가 전달되고, 데이터의 원본은 RowCache에 전달된다. 이후 Context에서 실제 데이터에 접근을 시도 하는 경우, Context에 존재하는 정보를 통해 RowCache의 데이터를 불러오게 된다. 이렇게 Context에 저장되는 정보를 Place Holder Object, Managed Object Fault 라고 부르며, 해당 정보를 사용해 RowCahce의 데이터를 불러 오는 과정을 Firing Faults, Fetc..
194. Transformable Transformable 영구 저장소에 저장된 데이터를 TableView에 표시한다. Contact.swift public class Contact: NSObject, NSCoding { @objc public var tel: String @objc public var fax: String @objc public var email: String init(tel: String, fax: String, email: String) { self.tel = tel self.fax = fax self.email = email super.init() } public static func sample() -> Contact { let telStr = String(format: "010-%04d-%04d", Int.ra..
193. Fetched Result Controller Fetched Result Controller FetchedResultController는 영구 저장소에서 가져온 내용을 관리하고 표시한다. 주로 TableView와 연동할 때 사용한다. Delegate 구현을 사용해 데이터를 모니터링하고 업데이트하며, Caching을 사용해 읽기 성능을 향상할 수 있다. 이 둘의 사용 여부에 따라 3가지 모드를 사용할 수 있다. Delegate Caching No Tracking Mode ❌ ❌ Memory-Only Tracking Mode ⭕️ ❌ Full Persistent Tracking Mode ⭕️ ⭕️ No Tracking Mode 가져온 데이터를 관리하는 최소한의 역할만 수행한다. Memory-Only Tracking Mode 가져온 데이터를 관리하며, M..
192. Expression Expression Format 문자열 대신 Class로 조건을 지정할 때 사용한다. 사용 빈도는 낮지만 평균, 합계 등의 연산에서 월등히 높은 성능을 보여준다. 대신 상대적으로 구현에 필요한 코드의 양이 많고, 동작 방식이 난해하다는 단점이 있다. Table View Cell의 디자인은 위와 같고, 평균 연봉은 해당 부서의 직원 목록에 접근한 뒤 연봉 데이터에 접근해 계산을 진행한다. ExpressionViewContoller.swift > tableView(_:cellForRowAt:) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.deq..
191. Predicate Syntax Predicate Syntax NSPredicate(format: String, arguments: CVaListPointer) NSPredicate(format: "target LIKE %@", "value") 여러 생성자 중 위의 생성자의 사용 빈도가 가장 높다. pram1 : Format 문자열 : 해당 문자열을 사용해 검색 조건을 지정 "targer LIKE %@"은 target 속성에 저장된 문자열을 검색한다. LIKE는 문자열 비교에 사용되는 연산자이고, Format 문자열 자체는 대소문자를 가리지 않지만 LIKE와 같이 연산자 등에 해당하는 키워드들은 대문자로 작성하는 것이 관행이다. 두 개 이상의 공백은 하나로 취급한다. %@는 포맷 지정자로 Swift의 것과 동일하다. param2 : 포..
190. Predicate Predicate Spotlight, CoreData에서 검색조건을 나타낼 때 사용되는 Predicate는 기술의 종류, DB의 종류에 상관없이 검색조건 지정이 가능하다는 장점이 있다. 구현 자체에서 대소문자를 구분하진 않지만 키워드는 대문자로, 그 외엔 lowerCamelCase로 작성하는 것이 보통이다. predicate를 사용하면 데이터 전체를 context에 전달하는 게 아닌 predicate의 조건에 맞는 데이터만 context에 전달하기 때문에 속도 향상을 기대할 수 있다. PredicateViewController.swift fetch() employee의 데이터를 이름순으로 정렬해 list 배열에 저장 TableView 새로고침 searchBarSearchButtonClicked() 선택한..
187 ~ 189. Fetch Request Fetch : CoreData에서 데이터를 읽어 오는 것 Fetch Request : 읽어올 데이터의 종류, Filtering 조건, 정렬 방식 등을 포함하는 객체 Request로 불리는 이유는 이를 직접 처리하지 않고 Context에 요청하고, Context가 대신해서 이를 처리하기 때문 Fetch Request 생성하기 FetchAllViewController.swift class FetchAllViewController: UITableViewController { var list = [NSManagedObject]() @IBAction func fetch(_ sender: Any?) { let context = DataManager.shared.mainContext } override func vi..