티스토리 뷰
최근 LiveActivity를 적용해보면서 App Extension 경험과
Tuist에 녹여내는 과정중에 삽질을 많이 하게 돼 복습도 할겸 블로깅을 해보려고 합니다!
겪었던 문제
1. Tuist를 통해 Widget Extension을 추가해야 함
2. Widget Extension에서도 Asset을 따로 만들어야 함
일반적으로는 App Extension의 경우 target membership을 아래와 같이 체크하면 해결 되는데,
tuist를 적용하게 되면 아래와 같은 방법으로 추가해줘야 합니다.
먼저 Project.swift 파일을 열기위해 아래 명령어를 터미널에 입력해주시고
tuist edit
Project 객체에 target을 추가해줍니다.
// Project.swift
let project = Project(
name: appName,
targets: [
// App target
.target(
name: appName,
destinations: .iOS,
product: .app,
// etc..
dependencies: [
// ...
.target(name: "WidgetExtension") // 1. 의존성 추가
]
),
// 2
// Extension target
.target(
name: "WidgetExtension",
destinations: .iOS,
product: .appExtension, // extension
bundleId: bundleId + ".WidgetExtension",
deploymentTargets: deploymentTarget,
infoPlist: .extendingDefault(with: [
"CFBundleDisplayName": "$(PRODUCT_NAME)",
"UIUserInterfaceStyle": "Light",
"NSExtension": [
"NSExtensionPointIdentifier": "com.apple.widgetkit-extension"
],
]),
sources: "WidgetExtension/Sources/**",
resources: "WidgetExtension/Resources/**",
settings: configureSettings(with: .appExtension)
),
],
additionalFiles: ["README.md"],
resourceSynthesizers: [
.assets(),
.fonts()
]
)
1. app target의 dependencies에 WidgetExtension의 의존성을 추가해줍니다
2. target을 하나 추가하여 appExtension을 추가해줍니다.
새롭게 만들어진 target의 경우 infoPlist, sources, resources 등 다시 만들어줘야 하는데요.
App target에서 했던것 처럼 똑같이 추가를 해주면 됩니다.
+ 추가
공통 모듈 생성
추가된 Widget Extension의 경우도 Asset을 따로 만들어줘야 하는데요.
저는 공통으로 사용되는 Asset이나 코드가 있는 경우 공통으로 관리되는 모듈을 하나 더 만드는 방법으로 구현했습니다.
다시 Project.swift를 열어주시고
let project = Project(
name: appName,
targets: [
.target(
name: appName,
destinations: .iOS,
product: .app,
bundleId: bundleId,
deploymentTargets: deploymentTarget,
infoPlist: .extendingDefault(with: infoPlist),
sources: ["App/Sources/**"],
resources: ["App/Resources/**"],
dependencies: [
.external(name: "RxSwift"),
.external(name: "RxCocoa"),
.external(name: "Alamofire"),
.external(name: "CoreXLSX"),
.external(name: "SwiftyJSON"),
.external(name: "SkeletonView"),
.target(name: "Common"), // 의존성 추가
.target(name: "WidgetExtension"), // 의존성 추가
],
settings: configureSettings(with: .app)
),
.target(
name: "WidgetExtension",
destinations: .iOS,
product: .appExtension,
bundleId: bundleId + ".WidgetExtension",
deploymentTargets: deploymentTarget,
infoPlist: .extendingDefault(with: [
"CFBundleDisplayName": "$(PRODUCT_NAME)",
"NSExtension": [
"NSExtensionPointIdentifier": "com.apple.widgetkit-extension"
],
]),
sources: "WidgetExtension/Sources/**",
dependencies: [
.target(name: "Common") // 의존성 추가
],
settings: configureSettings(with: .appExtension)
),
.target(
name: "Common", // 공통으로 사용해야할 코드가 있을 경우 여기에 코드 분리
destinations: .iOS,
product: .framework,
productName: "Common",
bundleId: bundleId + ".Common",
deploymentTargets: deploymentTarget,
sources: "Common/Sources/**"
),
]
)
위와 같이 'Common' 이라는 모듈을 만들었습니다.
폴더 구조는 아래와 같아요.
폴더구조
Usage
공통으로 사용하는 framework (Common)
// Common.swift
import ActivityKit
public struct WidgetExtensionAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here!
public var busNumber: Int
public var currentBusStop: String
public var stopLeft: Int
public var totalStop: Int
public init(busNumber: Int, currentBusStop: String, stopLeft: Int, totalStop: Int) {
self.busNumber = busNumber
self.currentBusStop = currentBusStop
self.stopLeft = stopLeft
self.totalStop = totalStop
}
}
// Fixed non-changing properties about your activity go here!
public var currentBusStopInfo: String
public init(currentBusStopInfo: String) {
self.currentBusStopInfo = currentBusStopInfo
}
}
NOTE
struct, 변수들을 public 및 초기화(init)시켜줘야 다른 파일에서도 import해서 사용할 수 있습니다.
public을 붙이는 이유는 접근제어자 를 참고해주세요~!
사용방법은 아래와 같습니다.
저는 WidgetExtensionAttributes를 App, WidgetExtension 두 군데에서 다 사용하기 위해 Common 모듈에 따로 추가했습니다.
[App] LiveActivitiyManager
[WidgetExtension] WidgetExtensionLiveActivity
이외에도 Color, Font 등 각 모듈에서 공통으로 사용하는게 있다면 한곳에서 관리하고 가져오는 방법으로 구현하도록 했습니다.
물론 이 방법이 답은 아니라고 생각합니다.
만약 다른 모듈에서 Color가 하나만 필요할 경우에도 Common 모듈을 import 해야할까? 라는 의문이 생기게 되네요.
이런 경우는 따로 import 하지않고 해당 모듈에서만 필요한 Color를 사용한다던지 할것 같습니다.
이 부분은 좀더 익숙해져보고 다른분들에게 조언을 한번 구해보고 수정해보도록 하겠습니다. :)
오늘은 LiveActivity를 적용해보면서 아래의 방법들에 대해 배워갈 수 있었던것 같습니다.
1. Widget Extension을 적용하는 방법
2. tuist와 같이 사용하는 방법,
3. 공통으로 사용하는 경우 하나의 framework로 관리하는 방법
하나씩 tuist 기능을 알아가면서 일단은 정리하고 있지만 추후 새롭게 알게 되는게 있으면 수정하도록 하겠습니다.
참고
1.
'iOS' 카테고리의 다른 글
[iOS] 고해상도 이미지 다운시 성능 개선 (Image DownSampling) (2) | 2024.10.11 |
---|---|
[iOS] Tuist (feat. xcproj 충돌) (5) | 2024.09.02 |
[SwiftUI] @StateObject와 @ObservedObject의 차이점 (0) | 2024.07.25 |
[iOS] GCD - SerialQueue, ConcurrentQueue vs sync, async (0) | 2024.05.12 |
[iOS] ITMS-91053: Missing API declaration (Privacy Manifests) (0) | 2024.04.10 |
- Total
- Today
- Yesterday
- RTCCameraVideoCapturer
- Swift ModernRIBs
- Swift joined()
- CS 네트워크
- Swift final
- Swift inout
- 원티드 프리온보딩
- Swift 프로그래머스
- Swift RIBs
- swift programmers
- RIBs tutorial
- Swift 알고리즘
- Swift init
- swift (programmers)
- Swift 프로퍼티
- Swift 내림차순
- Class
- Swift joined
- Combine: Asynchronous Programming with Swift
- Swift
- swift protocol
- removeLast()
- swift reduce
- ios
- 2023년 회고
- Swift Leetcode
- iOS error
- swift property
- swift 고차함수
- Swift Error Handling
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |