Unit Test 할 때 @testable의 역할이 뭘까 ?
·
📱 iOS/Swift
문제 상황MHDomain이라는 모듈 안에 MHDomain 동적 라이브러리와 MHDomainTests 정적 라이브러리가 있고,MHPresentation 모듈 안에 MHPresentation 동적 라이브러리와 MHPresentationTests 정적 라이브러리가 있다.테스트를 진행할 때 import MHDomain 을 해주어야 하는데,이 때 import 앞에 @testable 키워드를 사용할 수 있다.무슨 역할을 하는 지 알아보자 문제 해결@testable 키워드테스트 대상 모듈의 접근 수준에 영향을 주는지 여부이다.테스트 접근성 증가:Swift의 기본 접근 수준은 internal인데, 즉 동일 모듈 내에서만 접근할 수 있는 게 기본이다.@testable import를 사용하면 테스트 모듈에서 interna..
Swift의 전역 변수 초기화 시점
·
📱 iOS/Swift
문제 상황Swift Concurrency를 공부하며 스레드 안전성을 알아보던 중 흥미로운 얘기를 듣게 되었다.let logger = Logger( subsystem: "com.example.apple-samplecode", category: "Root View")위 전역변수 logger 코드는 언제 실행될까 ??전역변수니까 시작 시점에 초기화가 될까 ?답은 아니다. 왜 그런지 알아보자 문제 해결C언어와 Objective-C의 전역변수C언어와 Objective-C에서의 전역변수는 시작 시점에 초기화가 되는 게 맞다.그러나, 프로그램 시작 시간에 아주 나쁜 영향을 줄 수 있는 동작이 된다. Swift의 전역변수Swift는 위 문제점을 인지하고 방지하고자 전역변수를 지연(= lazy) ..
디버깅할 때, print가 아닌 OSLog 사용을 위한 Logger 구현
·
📱 iOS/Swift
문제 상황우리가 평소 디버깅을 위해 흔히 사용하는 print는 간단한 출력에는 유용하지만, 다음과 같은 단점이 있다성능: print는 출력 결과를 처리하는 동안 메인 스레드에서 실행되어 앱 성능에 영향을 줄 수 있다.레벨 구분 없음: print는 메시지를 구분할 방법이 없어, 로그의 중요도(예: 디버그, 정보, 에러 등)를 명확히 알기 어렵다.릴리스 빌드에서의 노출: print는 릴리스 빌드에서도 동작하며, 개발 중 남긴 로그가 사용자에게 노출될 위험이 있다.검색 및 필터링 불편: Xcode의 콘솔에서 print 로그는 별도의 태그 없이 출력되므로 특정 로그를 찾기 어렵다.본 편에서는 print가 아닌, OSLog를 사용하기 위해 어떻게 Logger를 구현했는지 알아보겠다! 문제 해결개요OSLog는 pr..
[UIKit] iOS 15.0 이상에서 UIButton 안에 있는 이미지 사이즈 조절하기
·
📱 iOS/UIKit
문제 상황버튼에 레이아웃을 아무리 건드려도 버튼 안에 들어있는 이미지는 늘어나지 않는다..!버튼 안에 있는 이미지 사이즈 조절하는 방법문제 해결개요현재 코드는 이렇게 버튼에만 레이아웃이 걸려있다.private let likeButton = UIButton(type: .custom)likeButton.setImage(.likeFill, for: .normal)likeButton.setAnchor( top: bookCoverView.bottomAnchor, trailing: dropDownButton.leadingAnchor, constantTrailing: 10, width: 40, height: 40)위 문제를 해결하기 위해 구글링 한 결과 4가지 정도 알아냈다.UIButton의 ContentEdg..
[UIKit] 런타임 시점에 Constraint를 조절하여 애니메이션 구현하기
·
📱 iOS/UIKit
문제 상황홈 화면에서 컬렉션 뷰를 통해 책들을 Flow하게 보여준다. 그리고 책을 생성하기 위해서는 우측 하단의 Floating 버튼이 있는데,이 버튼이 마지막 행의 오른쪽 책을 가리기 때문에 유저에서 ux적으로 불편함을 줄 수 있을 것이라 생각했다.이 문제를 해결해 나간 과정을 서술해보겠다.문제 해결아이디어플로팅 버튼은 우측 하단에 계속 띄워진 채 존재한다.마지막 행의 오른쪽 셀이 문제기 때문에 팀원과 논의한 끝에 ‘컬렉션뷰의 맨 아래에 도달하면 버튼을 숨기면 좋겠다’고 결론이 났다.그래서 버튼을 깜빡거리게 isHidden과 같은 요소를 사용할까? 했지만,유저에게 재미를 주기 위해 컬렉션 뷰 아래 바닥에 닿으면 아래로 슝 사라지고, 위로 스크롤하면 슝 올라오게 하려고 했다.(슝 이란 말로밖에 형용할 수..
[iOS] SwiftLint 적용 & 겪은 에러 해결과정 기록
·
📱 iOS/Swift
SwiftLint 적용 & 겪은 에러 해결과정 기록첫 번째 에러: '.xcfilelist'처음 에러는 .xcfilelist에서 겪었는데, Secret.xcconfig로만 설정해둬서 발생한 문제였다.아래와 같이 Secret.xcconfig 하나, Pods-IssueTracker.debug.xcconfig하나 각각 넣어줘서 해결했다. (맞는지 모르겠음...)  두 번째 에러: SandBoxBuild Settings - User Script Sandboxing을 No로 설정해서 보안 이슈 만들어버림 (나중에 처리) 세 번째 에러: Lint 적용이 이상함excluded에 Pods를 넣어도 계속 외부 라이브러리의 lint까지 에러를 잡았는데, 이건 캐시 문제인지..? swiftlint clear-cache 명령을..
[디자인패턴] 프로젝트에 Coordinator Pattern 적용 (3) - AppCoordinator 관리 & 순환참조 문제 해결
·
🖥️ Computer Science/👨🏻‍🎨 Design Pattern
AppCoordinator가 사라져서 Main 화면 Issue List가 사라지는 문제 해결기존 내 코드에는 다음과 같은 문제가 있었다.다른 곳에서는 weak var coordinator로 weak 키워드와 함께 관리가 되는데하필 메인 화면인 IssueList에서만 weak를 사용하면 앱이 더이상 동작하지 않는다.지난 번 팀원에게 내 SceneDelegate에서 AppCoordinator 관리가 잘못되었다고 짚어주셨다. 기존에 잘못된 내 코드class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? let navigationController = UINavigationController() func sce..
[iOS] Dynamic Framework로 모듈화 진행하기
·
📱 iOS
Dynamic Framework로 모듈화한 과정Dynamic Framework를 사용했다.New - project 생성 후 그 안에 파일을 타겟 설정해서 채워넣고 빌드를 한다.위 프로젝트를 종료하고, 위 디렉토리 전체를 IssueTracker 안에 넣는다.xcworkspace를 켜서 맨 바깥에 .xcodeproj에 대한 Reference만 추가 하다가 알게된 TMIFoundation에 Combine은 내가 아는 Combine과 다름sink와 같은 것들은 import Foundation만 해서는 안됨Command SwiftVerifyEmittedModulelnterface failed with a nonzero exit code 에러가 뜨면 Build Libraries for Distribution 옵션을..
[디자인패턴] 프로젝트에 Coordinator Pattern 적용 (2) - 코디네이터 분리
·
🖥️ Computer Science/👨🏻‍🎨 Design Pattern
지난 번에 코디네이터 패턴을 적용해보며초반에 잘못 이해한 코디네이터아래 이미지는 잘못된(?) 이미지임, 개선 전 이미지 처음에 IssueCreator와 Assignee는 Issue List위에서 present 되는 방식이라,Issue List Coordinator 하나로만 작동하고, 내부 메소드로 상황에 맞는 ViewController를 띄워주면 된다고 생각했다.그러나 이건 OCP를 위배하는 코드라 판단, 아래와 같이 뷰컨트롤러와 코디네이터를 1:1 맵핑해주었다. 새로 적용해본 코디네이터Input에 대해 mermaid로 정리해봤다. 아래는 텍스트로 정리한 내용이다.처음에 앱이 실행되면 SceneDelegate에서 최상위 코디네이터인 AppCoordinator를 생성하고 해당 인스턴스의 .start() 메..
[디자인패턴] 프로젝트에 Coordinator Pattern 적용 (1) - 개념 & 도입 이유
·
🖥️ Computer Science/👨🏻‍🎨 Design Pattern
뷰컨트롤러의 역할 중 '화면 전환' 부분에 대한 관심 분리를 위해 코디네이터 디자인패턴을 적용해보려 한다.다른 블로그를 많이 보고, 내가 생각한 내용 위주로 현재 프로젝트에 도입하는 과정을 서술해보겠다.Coordinator Design PatternCoordinator 개념화면 전환만을 담당하는 것뷰 컨트롤러에서 present, dismiss, navi~.pushVC, navi~.popVC를 사용하여 화면 전환을 하곤 한다.그러나 이 또한, 뷰컨트롤러가 화면전환을 담당하고 있기 떄문에 SRP를 지키지 않음 Coordinator 적용 이유화면 전환만 담당하게끔 하여 뷰컨트롤러의 화면 전환 의존성을 제거함이로써 뷰컨트롤러는 View에 대한 처리만 할 수 있게 된다.현재 화면에 다른 뷰컨이 많이 쌓여 있을 때..