본문 바로가기

IOS

iOS - 프로젝트에 SPM 을 달아보자

종속성 관리를 위한 도구인 SPM 을 소개 하고자합니다.

기존에 Cocoapod(3st party) 으로 설치했던 라이브러리를 SPM(1st party) Xcode 내장 기능을 이용해 구성 했습니다.

공통적으로 사용 가능한 함수, 및 View 들의 대해 라이브러리를 발행하여 사용하는 방법입니다.


1. Package 생성

1-1. new → package 클릭

1-2. 해당 package를 git에 push 한다. (push 과정 생략) 

 

 

1-3. package.swift 편집어떻게 보면 라이브러리 자체 생성은 가능하다, 해당 git 의 주소를 spm 상에 붙이면 연동은 끝이다.

다만, 해당 package 의 옵션 설정이 중요하다.

 

 

import PackageDescription

let package = Package(
    name: "SPMTestProject",
    platforms: [
        .iOS(.v13)
    ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "SPMTestProject",
            targets: ["SPMTestProject"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
        .package(url: "https://github.com/SDWebImage/SDWebImageSwiftUI.git", from: "2.0.0")
    ],
    targets: [
//        sad
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.g
        .target(
            name: "SPMTestProject",
            dependencies: ["SDWebImageSwiftUI"],
            resources: [.process("Resources"), .process("earth.gif")]),
        .testTarget(
            name: "SPMTestProjectTests",
            dependencies: ["SPMTestProject"]),
    ]
)

- name : 라이브러리 이름

- platforms : 라이브러리 지원 기기의 버전을 설정 할수 있다. (iOS, driverKit, macOS, tvOS)

- dependencies : 현재 라이브러리의 의존성을 추가 할수 있다 (추가적인 라이브러리) → 의존성 추가후 해당 SPM 을 설치하면 의존성이 딸려 들어간다.

- targets : 현재 라이브러리의 의존성을 추가 한다 (dependencies)

- resource: GIF ,이미지, JSON 파일과 같은 리소스 디렉토리를 추가할수 있다. (asset 파일에 추가한것이 아닌, 따로 추가 했을경우)

- swift-tools-version : 지원하는 스위프트 언어 버전들을 나열합니다.

 

 

 

1-4. 예시로 추가한 디렉토리 구조는 다음과 같다

 

1-5. 현재 시간을 나타내는 함수

public struct TimeUtils {
    public static func getNowDateTime() -> Int? {
        
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyyMMddHHmm"
        formatter.locale = Locale(identifier: "ko_KR")
        let resultDate = Int(formatter.string(from: Date()))
        
        return resultDate
    }
}

 

 

1-6. 로컬 저장소에 있는 earth.gif 파일을 실행 시키기 위한 View -> SDWebImageSwiftUI 의존성 추가

import SwiftUI
import SDWebImageSwiftUI

public struct AnimateView: View {
    
    public init() { }
    
    public var body: some View {
            
        VStack {
            AnimatedImage(name: "earth.gif", bundle: .module)
                .indicator(.activity)
                .frame(width: 100, height: 100)
                .aspectRatio(contentMode: .fit)
                .transition(.fade(duration: 0.5))
        }
    }
}

1-7. Asset 파일에 있는 이미지를 가져와서 나타내는 뷰

import SwiftUI

public struct AssetImageView: View {
    
    public init() { }
    
    public var body: some View {
        Image("test1", bundle: .module)
            .resizable()
            .frame(width: 200, height: 200)
    }
}

 

1-8. 그냥뭐.. 텍스트뷰

import Foundation
import SwiftUI

public struct TextView: View {
    public init() { }
    
    public var body: some View {
        VStack {
            Text("SPM 테스트 뷰")
                .frame(height: 300)
                .background(Color.red)
                .foregroundColor(.white)
        }
    }
}

 

- Package.swift 상에 플랫폼 버전을 표기 했기때문에, 뷰단에서 따로 버전 지정을 안해줘도 괜찮다. 만약 설정을 안해준다면

뷰단에서 @available 를 추가 해줘야하는 불편함이 생길수 있다.

- 이미지 같은경우 bundle 관련 메소드가 있는것으로 설정 해줘야한다.

- 뷰를 호출할때 초기화 를 안해줄경우 다음과 같은 오류가 발생할수 있다 -> initalizer is inaccessible due to 'internal' protection level 

- 뷰에 파라미터를 전달할때도 init 를 통해 전달 해야한다.


2.  Package 적용

2-1. 적용 하고자하는 프로젝트 → Build Phases → + 버튼 클릭

2-2. 하단 Add Other… 클릭후 Add Package Dependency… 클릭

2-3. 주소 : 깃헙 클론에 사용할 주소를 추가합니다

   ex) (https://github.com/MoongGi/SPMTestProject.git)

현 프로젝트에 해당 라이브러리를 추가합니다 버전 및 브런치는 환경에 맞게 구성 해주세요.

 


3.  적용

Package 추가를 완료했다면 본 소스에서 import 를 하여 사용할수 있다.

import SwiftUI
import SPMTestProject

struct ContentView: View {
    var body: some View {
        VStack {
           TextView()
            
           AnimateView()
           
           AssetImageView()
            
        }.onAppear {
           print(TimeUtils.getNowDateTime())
        }
    }
}

대충 결과..


4.  Package 업데이트

 

3-1. 디렉토리 라이브러리 우측 클릭후 → Update Package 클릭하여 업데이트

→ Develop 기준으로 맞춰놨기에 라이브러리 소스를 Develop 으로 업데이트 해야한다.


마치며

기본적으로 SPM 생성 과정 과 적용은 간단한거 같다.

실제 프로젝트 적용하다가 라이브러리 명을 여러번 바꾼적이 있었는데 잘 바뀌지가 않아 생각보다 고생한거 같다 -_- (캐시지우고 삽질 진행) 여러 프로젝트를 적용하면서 공통적으로 사용할수 있는 함수, 뷰에 대한 처리로는 좋은거같다

 

 

참고

https://medium.com/24stechblog/manage-resources-by-swift-package-manager-6993dc89279d

 

Manage resources by Swift Package Manager

As iOS developers, we often need to manage many resources to develop new features or UI. Things may go quite smoothly for a one man team…

medium.com

https://zeddios.tistory.com/1059

 

Bundling Resources with a Swift Package

안녕하세요 :) Zedd입니다. Resource를 포함한 Package를 만들어서 해당 Package를 사용중인 프로젝트에서 어떻게 Resource를 불러오는지 공부해보려고 합니다. # Swift Package만들기 Resource용으로 Package를 만

zeddios.tistory.com