[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple 101

[UIKit] Compositional Layout Example from Apple Sample Code (1)

Compostional Layout을 조금 더 잘 활용하고 싶어서 학습자료를 찾던 중 Apple Sample Code에서 너무 좋은 레퍼런스를 찾아서 이를 하나씩 정리해본 자료입니다. 🙃 Compositional Layout? Compositional Layout은 유연한 시각적 배열로 아이템들을 결합할 수 있는 레이아웃 객체이다. 이는 CollectionViewLayout의 한 타입인데, 작은 구성요소를 전체 레이아웃으로 결합하여 컨텐츠에 대한 시각적 배열을 구축할 수 있다. Compositional layout은 시각적으로 뚜렷한 그룹으로 나뉘는 하나 이상의 Section으로 구성된다. 각 Section은 표시하려는 가장 작은 데이터 단위인 Item으로 구성된다. Group은 항목을 수평, 수직 또는..

🍎 Apple/UIKit 2022.01.17

[iOS] 왜 UI는 메인 스레드에서 다룰까?

왜 UI는 메인 스레드에서 다룰까? 1. UIKit의 대부분 구성요소는 non-atomic하게 구성되어있는데, 이는 곧 Thread-safe하지 않다는 것을 의미한다. 모든 속성을 Thread-safe하게 설계하기엔 UIKit이 너무 방대한 프레임워크이다. 이를 억지로 보장하도록하는 것은 오히려 성능상으로 좋지 않다는 애플의 발표도 있다. 예를 들어 생각해보자. UITableView의 셀이 백그라운드 스레드에서 제거되었는데 다른 백그라운드 스레드가 해당 셀에 접근하려고하면 어떻게될까? 크래시가 발생할 것이다. 또 백그라운드 스레드의 Runloop에 특정 뷰에 대한 제거가 진행중에 있는데, 사용자가 해당 뷰를 탭하면 그 응답을 어떻게 처리해야할까? 어떤 스레드에서 해당 응답을 처리해야할지조차 애매하다. 2..

🍎 Apple/Question 2022.01.14

[Combine] share, multicast

share 하나의 upstream publisher의 output을 여러 subscriber들이 공유할 수 있도록 해준다. Example 1 guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { fatalError("Invalid URL") } let request = URLSession.shared.dataTaskPublisher(for: url).map(\.data).print().share() let subscription1 = request.sink(receiveCompletion: { _ in }, receiveValue: { print("Subscription 1") print($0) }) let sub..

[Combine] timer (by Runloop, Timer Class, DispatchQueue)

Combine을 통해 Timer를 생성하고 관리해보자. Runloop 입력소스 및 타이머 이벤트를 전달받는 인터페이스인 Runloop를 활용하여 Timer cacellable 객체를 생성할 수 있다. Runloop 공식문서에서 cacellable 객체를 생성하는 메서드를 확인할 수 있다. (마지막 schedule 메서드) Example let runLoop = RunLoop.main let subscription = runLoop.schedule(after: runLoop.now, interval: .seconds(2) , tolerance: .milliseconds(100)) { print("Timer fired") } runLoop.schedule(after: .init(Date(timeInterva..

[Combine] Operator (4): Sequence Operator

Sequence Operator Combine에서 Operator는 Publisher를 가공해 다른 형태나 구성으로 변경해주는 역할을 한다. Upstream으로부터 전달받은 데이터를 가공하여 downstream으로 전달하는 것이다. 그 중 배열로 이루어진 Output을 변환하는 Operator(Sequence Operator)를 정리해보겠다. min and max Example let publisher = [1,-45,3,45,100].publisher publisher .max() .sink { print($0) } Output 100 publisher가 finish될 때까지 기다리고 이 후 연산을 처리한다. 데이터 중 max(min)값을 반환한다. first and last Example let pu..

[Combine] Operator (3): Combining Operator

Combining Operator Combine에서 Operator는 Publisher를 가공해 다른 형태나 구성으로 변경해주는 역할을 한다. Upstream으로부터 전달받은 데이터를 가공하여 downstream으로 전달하는 것이다. 그 중 데이터를 추가 혹은 합성하는 Operator(Combining Operator)를 정리해볼까 한다. prepend Example let numbers = (1...5).publisher let publisher2 = (500...510).publisher numbers.prepend(100,101) .prepend(-1,-2) .prepend([45,67]) .prepend(publisher2) .sink { print($0) }Output 500 501 502 50..

[Combine] Operator (2): Filtering Operator

Filtering Operator Combine에서 Operator는 Publisher를 가공해 다른 형태나 구성으로 변경해주는 역할을 한다. Upstream으로부터 전달받은 데이터를 가공하여 downstream으로 전달하는 것이다. 그 중 데이터를 필터링해주는 Operator(Filtering Operator)를 정리해보자. filter Example let numbers = (1...20).publisher numbers.filter { $0 % 2 == 0 } .sink { print($0) }Output 2 4 6 8 10 12 14 16 18 20 조건에 통과하는 데이터들만 반환한다. removeDuplicates Example let words = "apple apple apple fruit ..

[Combine] Operator (1): Transforming Operator

Transforming Operator Combine에서 Operator는 Publisher를 가공해 다른 형태나 구성으로 변경해주는 역할을 한다. Upstream으로부터 전달받은 데이터를 가공하여 downstream으로 전달하는 것이다. 그 중 데이터의 형태(타입)를 바꿔주는 Operator(Transforming Operator) 정리해볼 것이다. collect Example ["A","B","C","D","E"].publisher.collect(3).sink { print($0) } Output ["A", "B", "C"] ["D", "E"] Input 데이터를 모아서 Array로 한번에 반환하도록 처리한다. 파라미터로 숫자를 넣어서 몇개를 하나로 묶을지도 결정할 수 있다. (default는 모든 ..

[CoreData] 기초개념 (3): Entity Relationship

Entity Relationship 해당 버튼을 누르면 Entity를 관계그래프 형태로 확인할 수 있다. 이 때 표현된 Entity 둘을 마우스를 통해 드래그를 하여 이어주면 Relationship을 설정할 수 있다. Relationship이 설정된 모습이다. 각 Entity에게 Relationship은 서로를 의미하게 된다. 데이터베이스 모델처럼 관계 타입도 설정할 수 있다. (To Many or To One) relationship도 attribute와 유사하게 사용하면 된다.

[CoreData] 기초개념 (2): Query & Sorting

데이터베이스에서 그랬듯 Coredata에서도 조건을 주어 원하는대로 데이터를 가져올 수 있다. 또한 정렬순서도 결정할 수 있다. 조건을 줄 때는 NSPredicate 객체를, 정렬을 할 때는 NSSortDescriptor를 사용한다. NSPredicate 어떻게 데이터를 필터링하고 불러올지를 결정하는 객체이다. SQL에서 쿼리문을 날리는 것과 비슷하게 쿼리문을 작성하고 요청할 수 있다. let predicate = NSPredicate(format: "title CONTAINS %@", searchText) request.predicate = predicate NSPredicate의 쿼리문을 작성하고, 거기에 넣어줄 값이 필요하다면 뒤에 작성한다. 위는 NSPredicate의 예시이다. title att..