본문 바로가기

iOS App development

(57)
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..
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() 선택한..
169 ~ 170. Timer & Runloop and Concurrency Programming Timer & Runloop Timer는 지정된 주기마다 반복되는 코드를 실행할 때 사용할 수 있다. Timer가 제공하는 API는 단순하지만 Runloop에 대한 이해가 없다면 원하는 결과를 얻기 어렵다. Runloop 다양한 이벤트를 처리하기 위해 사용하는 Event Processing Loop이다. 앱이 시작되면 Main Thread에서 동작하는 Runloop가 자동으로 생성된다. Background Thread에서 Runloop가 필요한 경우 직접 구성해야 한다. Runloop는 Thread에서 발생하는 Event Source를 감시한다. iOS는 Event Source로부터 새로운 Event가 도착하면 Thread를 깨워 Runloop로 이벤트를 전달한다. 이후 Runloop는 등록된 Handl..
168. Debugging Auto Layout Debugging Auto Layout Auto Layout에서 오류가 발생하는 이유는 필요한 제약이 추가되지 않은 경우 필요 이상의 제약이 중복돼 있는 경우 처럼 명확하다. 필요한 제약만 올바르게 추가한다면 문제가 발생하는 경우는 없다. 하지만 코드를 사용해 제약을 추가하는 경우 앱을 실행할 때까지 결과를 확인할 수 없으므로, 이러한 규칙을 지키기 어려울 때도 있다. Missing Constraints 예시는 위와 같다. leading 제약만 추가돼있고, Indicator가 붉은 색으로 표시된다. Interface Builder에서는 여러 방식으로 오류를 표현한다. Design Time Visual Indicator Scene에서 해당 제약을 붉게 표현한다. Constraint Issue Indicat..
167. Constraints with Code #5 Constraints with Code #5 Constraint animation 제약에 Animation을 추가해 본다. // // AnimatingLayoutChangesViewController.swift // Constraints with Code Practice // // Created by Martin.Q on 2021/12/20. // import UIKit class AnimatingLayoutChangesViewController: UIViewController { @IBOutlet weak var pinkView: UIView! @IBOutlet weak var heightConstraint: NSLayoutConstraint! @IBOutlet weak var widthConstrai..
166. Constraints with Code #4 Constraints with Code #4 Align Center 사용할 Scene은 위와 같다. Label을 중앙에 배치하고, 파란색 View를 아래에 배치한다. 단, Label은 Intrinsic Size를 사용하도록 크기 제약은 추가하지 않는다. Label과 파란색 View의 간격은 10pt, 파란색 View의 높이는 5pt, 파란색 View의 너비는 Label의 너비와 같도록 제약을 추가한다. 추가된 모습은 위와 같다. NSLayoutConstraint로 제약 추가하기 func layoutWithInitializer() { label.translatesAutoresizingMaskIntoConstraints = false tealView.translatesAutoresizingMaskIntoCo..
165. Constraints with Code #3 Constraints with Code #3 Custom Header View 화면 상단에 View를 배치하고, 너비는 margin에 관계없이 모두 채울 수 있도록 제약을 추가한다. 높이는 100pt로 고정한다. Scene은 위와 같다. 추가되는 제약은 위와 같다. 이때 추가하는 대상은 Safe Area가 아닌 View로 설정해야 하고, Constrain to margins 속성은 비활성화해야 한다. 이렇게 추가하면 System UI의 영역까지 덮게 된다. 만약 System UI를 침범하지 않게 하려면 Safe Area를 기준으로 추가하면 된다. 변경하면 위와 같은 모습이 된다. // // CustomHeaderViewController.swift // Constraints with Code Practi..
164. Constraints with code #2 Constraints with code #2 top, leading, trailing, bottom // // FillParentViewController.swift // Constraints with Code Practice // // Created by Martin.Q on 2021/12/17. // import UIKit class FillParentViewController: UIViewController { @IBOutlet weak var bottomContainer: UIView! @IBOutlet weak var orangeView: UIView! override func viewDidLoad() { super.viewDidLoad() layoutWithInitializer() } } ex..
163. Constraints with Code #1 Constraints with Code #1 제약을 코드를 통해 적용하는 법에 대해 정리한다. 제약은 NSLayoutConstraint 클래스로 구현돼있고, 해당 클래스의 멤버를 통해 제약을 활용할 수 있다. Interface Builder를 통해 제약을 추가하는 것보다 어렵고 많은 코드를 입력해야 하지만, 동적으로 적용되는 제약을 자유롭게 적용할 수 있다. 제약을 추가하는 데에는 두 개의 멤버가 제공된다. constraints(withVisualFormat:) 메서드는 Visual Format Language를 통해 제약을 생성할 때 사용된다. init(item:) 메서드는 가장 기본적인 제약을 생성할 때 사용된다. item1.attr = multiplier * item 2.attr + constant..