| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- boostcamp
- 디자인패턴
- 후기
- WWDC
- development
- Hello
- 단위 테스트
- 부스트캠프
- ios #swift #uialertcontroller #메서드 스위즐링
- Cocoa Internals
- Swift
- 알고리즘
- Algorithm
- Design Pattern
- OS
- 부트캠프
- SwiftUI
- Tistory
- 커스텀 뷰
- 개발
- Opensource
- 네이버 부캠
- rxswift
- notion
- World
- 코코아 인터널스
- IOS
- Today
- Total
목록Programming (50)
꿈돌이랜드
최근 프로젝트의 규모가 커짐에 따라 모듈화(Modularization) 작업을 진행했습니다. 공통으로 사용되는 UI 컴포넌트와 디자인 리소스(Color, Image 등)를 Shared 모듈(Dynamic Framework)로 분리하는 것이 목표였습니다.하지만, 앱 타겟(App Target)에 있던 리소스를 별도의 프레임워크로 옮긴 후 실행해보니 색상이나 이미지를 불러오지 못하는 문제가 발생했습니다.이 과정에서 겪은 번들(Bundle) 문제와, Xcode 16 (Swift 5.9+) 환경에서 이를 우아하게 해결해 준 #bundle 매크로에 대해 공유합니다.1. 문제 상황: 리소스가 왜 nil일까?보통 우리는 Asset Catalog에 있는 색상을 사용할 때 다음과 같이 호출합니다.// 일반적인 호출let ..
들어가며LetSwift 2025에 오거나이저로 참여하며 앱에 Live Activity를 넣기로 했다, 막상 시작하니... 생각보다 훨씬 복잡했다. Push-to-Start 토큰이 뭔지도 몰랐고, FCM으로 Live Activity를 어떻게 시작하는지도 감이 안 잡혔다.결과적으로는 성공했지만, 그 과정에서 정말 많은 시행착오가 있었다. 날짜 파싱이 안 돼서 머리를 쥐어뜯기도 했고, 토큰 관리 때문에 메모리 누수를 만들기도 했다. 이 글에서는 그런 삽질들을 가감 없이 공유해보려고 한다.일단 설계부터Let'Swift는 A트랙이랑 B트랙이 동시에 진행된다. 그래서 처음부터 "트랙별로 독립적인 Live Activity를 띄워야겠다"고 생각했다. 문제는 Live Activity의 구조를 이해하는 게 쉽지 않았다는 ..
Swift Concurrency 성능 조사참고한 글!Core 수만큼 정확하게 스레드를 생성하는가?코어 수 만큼 아주 정확하게 스레드를 생성하지는 않음.필요에 따라 더 스레드를 만들어서 Priority가 High인 작업들 속에서 상대적으로 낮은 작업의 실행이 영원히 기다리지 않도록 방지한다.그 반대의 경우도 마찬가지 (먼저 실행중인 task가 low이고 오래동안 점유 중 일때, high인 task가 들어올 경우)우선순위가 다른 여러 작업이 있을 때 Suspension points에서 높은 확률로 우선순위가 높은 작업이 스레드를 할당받는다.현재 실행해야 하는 작업 중 우선순위가 가장 높은 작업이 스레드를 코어 수만큼 차지하고 있다면, 우선순위가 그보다 낮은 작업을 위해 별도 스레드가 추가된다. 따라서 스레드..
Modern SwiftUI: Identified arrays이 포스팅은 위 링크를 기반으로 작성했습니다.IdentifiedArray가 필요한 이유보통 SwiftUI에서 리스트 뷰를 구현할 때 ForEach 구문으로 리스트 데이터를 순차적으로 표시하는 케이스가 많습니다.그런 경우 보통 다음과 같이 구현하게 됩니다. struct StandupsList: View { @State var standups: [Standup] = […] var body: some View { List { ForEach(standups) { standup in StandupRow(standup: standup) } } } }그런데 보통 뷰 레이어에서 다시..
Swift Concurrency사내에서 Swift Concurrency 스터디를 진행했습니다.Swift Concurrency는 Swift5.5 버전 부터 도입된 Swift 언어 차원의 비동기 처리 방식입니다Documentation이 글에서는 개인적으로 Swift Concurrency를 공부하면서 중요하게 깨달은 내용에 대해 서술합니다.1. 어떤 actor에 해당 변수, 함수가 “선언”되어있는지가 중요하다.GCD의 경우 선언이 중요한게 아니라 런타임에 어떤 dispatchqueue에 해당 작업이 들어가서 실행되는지가 중요했습니다.Swift Concurrency의 경우는 해당 변수와 함수가 “선언된 위치”가 곧 어떤 스레드(엄밀히 말하면 actor)에서 동작할지를 결정합니다.이를 흔히 다양한 교육자료에서 격..
메서드 스위즐링이란?메서드 스위즐링은 런타임에 함수의 구현부를 뒤섞는 방법을 말합니다.구현 방법은 보통 다음과 같이 이뤄집니다.보통 class_getInstanceMethod 나 class_getClassMethod 와 같은 방법을 사용해서 각 메서드의 셀렉터를 가져오고각각을 method_exchangeImplementation으로 뒤바꾸어 구현을 바꾸어서 구현, appdelegate 같은 곳에서 swizzle을 한번 실행시켜줍니다.단, 각 메서드는 @objc 런타임에 노출되어야 하고, dynamic으로 마킹되어있어야 함extension에 정의된 경우는 자동으로 dynamic처리가 된 것으로 칩니다.import UIKitfileprivate var swizzleEnabled = falseextension..
Dependency lifetimesHow task locals workDependency 프로퍼티 래퍼가 초기화되면, 그 순간 dependency의 현재 상태를 캡처합니다.@TaskLocal 변수가 새로운 비동기 task들로부터 상속되는 것과 비슷합니다.TaskLocal 변수는 withValue 메서드 Scope 내에서만 값을 변경 가능합니다.이는 TaskLocal 변수가 동시성 환경에서 Thread-safe하게 만듦니다.단, 상속된 Task의 Scope 내에서는 부모 Task의 TaskLocal 값을 상속받습니다.하지만, 일반적으로 task local은 escaping closure 범위를 넘어설 때마다 오버라이드를 잃습니다.아래 예시 코드 처럼 withValue로 오버라이드한 값이 asyncAfte..
프림 알고리즘프림 알고리즘은 크루스칼 알고리즘과 마찬가지로 MST를 구하는 알고리즘동작임의의 정점을 선택해서 비어있는 T 트리에 포함시킨다.T에 있는 노드와 T에 없는 노드 사이의 간선 중 가중치가 최소인 간선을 찾는다.찾은 간선이 연결하는 두 노드 중, T에 없던 노드를 T에 포함시킨다.이 때, 1에서 찾은 간선도 같이 T에 포함된다.모든 노드가 T에 포함될 때 까지, 1, 2를 반복한다. 아래는 그림으로 설명된 것입니다.임의의 정점을 선택해서 빈 T에 포함시킨다.예를 들어 1을 선택합니다.T에 있는 노드와 T에 없는 노드 사이의 간선 중 가중치가 최소인 간선을 찾는다.빨간색과 파란색을 연결하는 간선 중 가중치가 최소인 것을 찾는다. 1-3과 1-2 중, 가중치가 더 작은 간선은 가중치가 4인 1-3을..