ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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
        }
    }
    
    

    이렇게 접근 하면 성공

    댓글

Designed by Tistory.