-
Tuist활용하여 멀티 모듈 SwiftUI 프로젝트 생성하기개발/Swift 2024. 10. 15. 22:26
Swift UI 용으로 init 해줌 , 반드시 빈 폴더여야 함
tuist init --platform ios --template swiftui
tuist edit 하면 세팅할수있음
모듈형태면 Project가 아닌 Workspace사용하므로 Project 파일 지워버리고
Workspace 파일 생성함
let workspace = Workspace( name: "MyWeather", projects: [ "Projects/**" ] )
이렇게 그냥 간단지게 만들어버림
그러고 Project 폴더에
App - 메인
Module - 생성할 모듈
폴더를 생성함, 그러고 Project.swift 파일을 새로 만듬
나는 Network 모듈, Entity 모듈을 생성함
App에서 Project 객체를 생성
import Foundation import ProjectDescription let infoPlist: [String: InfoPlist.Value] = [:] let project = Project(name: "MyWeather", //이름 organizationName: "MyName", targets: [ Target(name: "MyWeather", platform: .iOS, product: .app, bundleId: "simon.kang.myweather", infoPlist: .extendingDefault(with: infoPlist), sources: ["Sources/**"], resources: ["Resources/**"], dependencies: [ .project(target: "Network", path: "../Network"), //에러나면 이거 지웠다가 나중에 추가 .project(target: "Entity", path: "../Entity"), ] ) ] )
번들 아이디, 이름 지정 해야 하고 파일경로 리소스 경로 지정해줬으니
이에 맞게 Sources, Resources폴더 생성 해야함
그러고 모듈에서도 똑같이 Project 생성하되
name 바꿔주고
product를 framework로 변경
dependencies는 빈배열로
import Foundation import ProjectDescription let infoPlist: [String: InfoPlist.Value] = [:] let project = Project(name: "Entity", organizationName: "MyName", targets: [ Target(name: "Entity", platform: .iOS, product: .framework, bundleId: "simon.kang.myweather", infoPlist: .extendingDefault(with: infoPlist), sources: ["Sources/**"], dependencies: [ ] ) ])
infoPlist 변수명같다고 compile 에러났지만 무시하니 사라졌음
Sources 폴더도 만들어줘야함
이러고 tuist generate
이렇게 세개 모듈 생김
이제 Project내부에 Source 폴더 추가해주고 파일 하나씩 아무거나 추가해줘야함
SwiftUI main view도 없으니 하나 만들어줌
import 까지 성공
외부 라이브러리사용
tuist edit → Tuist 폴더내부에 Dependencies파일 생성
import ProjectDescription let spm = SwiftPackageManagerDependencies( [ .remote(url: "<https://github.com/Alamofire/Alamofire.git>", requirement: .upToNextMajor(from: "5.10.0")) ]) let dependencies = Dependencies( swiftPackageManager: spm, platforms: [.iOS] )
이렇게 Spm 디펜던시추가함
그리고 이 라이브러리가 필요한 Network모듈 project에 dependencies 에 추가
let project = Project(name: "Network", organizationName: "MyName", targets: [ Target(name: "Network", platform: .iOS, product: .framework, bundleId: "simon.kang.myweather", infoPlist: .extendingDefault(with: infoPlist), sources: ["Sources/**"], dependencies: [ .external(name: "Alamofire") ] ) ])
이러고 tuist fetch
Resolving and fetching plugins. Plugins resolved and fetched successfully. Resolving and fetching dependencies. Installing Swift Package Manager dependencies. Fetching <https://github.com/Alamofire/Alamofire.git> from cache Fetched <https://github.com/Alamofire/Alamofire.git> from cache (1.83s) Computing version for <https://github.com/Alamofire/Alamofire.git> Computed <https://github.com/Alamofire/Alamofire.git> at 5.10.0 (0.46s) Creating working copy for <https://github.com/Alamofire/Alamofire.git> Working copy of <https://github.com/Alamofire/Alamofire.git> resolved at 5.10.0 Swift Package Manager dependencies installed successfully. Dependencies resolved and fetched successfully.
성공
Swift UI 용으로 init 해줌 , 반드시 빈 폴더여야 함
tuist init --platform ios --template swiftui
tuist edit 하면 세팅할수있음
모듈형태면 Project가 아닌 Workspace사용하므로 Project 파일 지워버리고
Workspace 파일 생성함
let workspace = Workspace( name: "MyWeather", projects: [ "Projects/**" ] )
이렇게 그냥 간단지게 만들어버림
그러고 Project 폴더에
App - 메인
Module - 생성할 모듈
폴더를 생성함, 그러고 Project.swift 파일을 새로 만듬
나는 Network 모듈, Entity 모듈을 생성함
App에서 Project 객체를 생성
import Foundation import ProjectDescription let infoPlist: [String: InfoPlist.Value] = [:] let project = Project(name: "MyWeather", //이름 organizationName: "MyName", targets: [ Target(name: "MyWeather", platform: .iOS, product: .app, bundleId: "simon.kang.myweather", infoPlist: .extendingDefault(with: infoPlist), sources: ["Sources/**"], resources: ["Resources/**"], dependencies: [ .project(target: "Network", path: "../Network"), //에러나면 이거 지웠다가 나중에 추가 .project(target: "Entity", path: "../Entity"), ] ) ] )
뭐 내용 별거없으니 패스 번들아이디 알아서 이름 알아서 그러고 파일경로 리소스 경로 지정해줬으니
이에 맞게 Sources, Resources폴더 생성 해야함
그러고 모듈에서도 똑같이 Project 생성하되
name 바꿔주고
product를 framework로 변경
dependencies는 빈배열로
import Foundation import ProjectDescription let infoPlist: [String: InfoPlist.Value] = [:] let project = Project(name: "Entity", organizationName: "MyName", targets: [ Target(name: "Entity", platform: .iOS, product: .framework, bundleId: "simon.kang.myweather", infoPlist: .extendingDefault(with: infoPlist), sources: ["Sources/**"], dependencies: [ ] ) ])
infoPlist 변수명같다고 compile 에러났지만 무시하니 사라졌음
Sources 폴더도 만들어줘야함
이러고 tuist generate
이렇게 세개 모듈생김
이제 Project내부에 Source 폴더 추가해주고 파일 하나씩 아무거나 추가해줘야함
SwiftUI main view도 없으니 하나 만들어줌
import 까지 성공
외부 라이브러리사용
tuist edit → Tuist 폴더내부에 Dependencies파일 생성
import ProjectDescription let spm = SwiftPackageManagerDependencies( [ .remote(url: "<https://github.com/Alamofire/Alamofire.git>", requirement: .upToNextMajor(from: "5.10.0")) ]) let dependencies = Dependencies( swiftPackageManager: spm, platforms: [.iOS] )
이렇게 Spm 디펜던시추가함
그리고 이 라이브러리가 필요한 Network모듈 project에 dependencies 에 추가
let project = Project(name: "Network", organizationName: "MyName", targets: [ Target(name: "Network", platform: .iOS, product: .framework, bundleId: "simon.kang.myweather", infoPlist: .extendingDefault(with: infoPlist), sources: ["Sources/**"], dependencies: [ .external(name: "Alamofire") ] ) ])
이러고 tuist fetch
Resolving and fetching plugins. Plugins resolved and fetched successfully. Resolving and fetching dependencies. Installing Swift Package Manager dependencies. Fetching <https://github.com/Alamofire/Alamofire.git> from cache Fetched <https://github.com/Alamofire/Alamofire.git> from cache (1.83s) Computing version for <https://github.com/Alamofire/Alamofire.git> Computed <https://github.com/Alamofire/Alamofire.git> at 5.10.0 (0.46s) Creating working copy for <https://github.com/Alamofire/Alamofire.git> Working copy of <https://github.com/Alamofire/Alamofire.git> resolved at 5.10.0 Swift Package Manager dependencies installed successfully. Dependencies resolved and fetched successfully.
성공
문제
1. SwfitUI의 view가 위 아래 잘린 형태로 노출이됨
코드로 별짓을 다해봐도 적용이 안됨, 커뮤니티 통해 얻은 소스 LaunchScreen 세팅이 없어서 그렇다는 이야기를 들음
자세히 알아보니 infoPlist에 원래 LaunchScreen 정보가 비어있더라고 들어있음
반면 내 infiPlist는 빈값을 넣어주어서 비어있는 상태였음
let infoPlist: [String: InfoPlist.Value] = [ "UILaunchScreen": [ "UILaunchBackgroundColor": "#FFFFFF" ] ]
이렇게 넣어주었다 배경색만 널어준건데 빈 Dictionary 넣어주어도 무방해보임 → 해결 완료
2. 모듈에서 번들 관리하기
Network 모듈에서 Secret.plist 파일을 두고 Bundle 접근하려니 불러오지 못함
extension Bundle { var apiKey: String? { guard let file = self.path(forResource: "Secret", ofType: "plist"), let resource = NSDictionary(contentsOfFile: file), let key = resource["APIKEY"] as? String else { print("API KEY를 가져오는데 실패하였습니다.") return nil } return key } } //사용 예시 let apikey = Bundle.main.apiKey
일반적으로 Bundle.main 접근을 하면 모듈이 아닌 메인 앱에서 접근하는듯 하고
Secret.plist 파일은 모듈 내부에 있으므로 찾지를 못함
해결을 위해서 모듈에서는 접근 방식을 달리 해야함
우선 모듈에서 Resource 폴더 생성후 Secret.plist을 집어 넣어주고 (파일 타겟 설정 확인)
Target 에서 경로 지정을 해주고 generate
resources: ["Resources/**"],
그리고 접근할떄 모듈 내부 Class (아무파일이나 상관없음) 를 사용한 번들 생성을 해야함
class BundleManager { static var apiKey: String? { let bundle = Bundle(for: BundleManager.self) guard let file = bundle.path(forResource: "Secret", ofType: "plist"), let resource = NSDictionary(contentsOfFile: file), let key = resource["APIKEY"] as? String else { print("API KEY를 가져오는데 실패하였습니다.") return nil } return key } }
이렇게 접근 하면 성공
'개발 > Swift' 카테고리의 다른 글
LiveActivity - Push Console로 테스트 해보기 (0) 2024.10.19 LiveActivity Dynamic island 구현하기 (3) 2024.10.16 Label Attribute 이미지 처리, 줄넘김 하기 (0) 2024.09.12 Contact Framework 사용하여 연락처 불러오기 (0) 2024.09.03 Compositional Layout+ Diffable Datasource 활용 가이드 (0) 2024.08.27