| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 | 31 |
- React #Web #프런트엔드
- 일임형
- 자바스크립트
- BFS
- MacOS
- programmers
- 파이썬
- frontend
- algoritms
- JS
- 자문형
- Objective-C
- IOS
- Python
- 백준
- 자료구조
- BAEKJOON
- algorithms
- 로보어드바이저
- 스택
- 트럼프
- Algorithm
- dfs
- JavaScript
- 알고리즘
- Swift
- 모던자바스크립트
- 신한투자증권
- Ai
- 큐
- Today
- Total
Step by Step
iOS 앱을 다이나믹 아일랜드에 연동하는 방법 (Live Activities 활용) 본문
YouTube Music과 같은 미디어 앱은
다이나믹 아일랜드(Dynamic Island)에 현재 재생 정보를 표시하여 사용자 경험을 크게 향상시킵니다.
Apple의 Live Activities와 ActivityKit 프레임워크를 사용하여 iOS 앱을 다이나믹 아일랜드 및 잠금화면과 연동하는 방법을 단계별로 설명하고자 합니다. 특히 미디어 앱의 경우, MediaPlayer 프레임워크를 함께 활용하여 재생 정보를 표시하고 제어하는 전체 과정을 다룹니다.
1. 프로젝트 기본 설정
가장 먼저, 프로젝트가 Live Activities를 지원하도록 설정해야 합니다.
- Info.plist 설정: Info.plist 파일에 NSSupportsLiveActivities 키를 추가하고, 값을 Boolean 타입의 YES로 설정합니다.
- Widget Extension 추가: 프로젝트에 새로운 Target으로 'Widget Extension'을 추가해야 합니다. Target 생성 시 'Include Live Activity' 옵션을 반드시 활성화해야 관련 파일들이 자동으로 생성됩니다.
기존 제가 설정했던 Info.plist 파일에는 Firebase App key와 App Store ID등이 있는데 동일한 파일에 추가를 해줍니다.
2. 표시할 데이터 모델 정의 (ActivityAttributes)
Live Activity에 표시될 데이터를 구조체 형태로 정의해야 합니다. 데이터는 정적인 데이터와 동적인 데이터로 구분하여 관리하는 것이 효율적입니다.
- ActivityAttributes (정적 데이터): Live Activity가 시작될 때 한 번만 설정되며 변경되지 않는 데이터를 정의합니다. (예: 앨범 제목, 플레이리스트 정보 등)
- ContentState (동적 데이터): 실시간으로 변경될 수 있는 동적인 데이터를 정의합니다. (예: 곡 제목, 아티스트, 재생 진행률, 재생 상태 등)
// MyActivityAttributes.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyActivityAttributes : NSObject
// Live Activity의 정적 데이터 (예: 트랙 이름, 아티스트 이름)
@property (nonatomic, copy) NSString *trackName;
@property (nonatomic, copy) NSString *artistName;
@end
@interface MyActivityStatus : NSObject
// Live Activity의 동적 데이터 (예: 재생 시간, 재생 상태)
@property (nonatomic, assign) NSTimeInterval playbackTime;
@property (nonatomic, assign) BOOL isPlaying;
@end
NS_ASSUME_NONNULL_END
2-1. Live Activity 시작 및 관리
Objective-C 코드에서 Live Activity를 시작하고 관리하기 위해서는 Swift 코드로 작성된 Activity 객체를 관리하는 브릿지 코드가 필요합니다.
// LiveActivityManager.h
#import <Foundation/Foundation.h>
#import "MyActivityAttributes.h" // 위에서 정의한 헤더 파일
NS_ASSUME_NONNULL_BEGIN
@interface LiveActivityManager : NSObject
+ (instancetype)sharedManager;
- (void)startLiveActivityWithTrackName:(NSString *)trackName artistName:(NSString *)artistName;
- (void)updateLiveActivityWithPlaybackTime:(NSTimeInterval)playbackTime isPlaying:(BOOL)isPlaying;
- (void)endLiveActivity;
@end
NS_ASSUME_NONNULL_END
// LiveActivityManager.m
#import "LiveActivityManager.h"
#import "YourProject-Swift.h" // Xcode가 자동으로 생성하는 Swift 브릿지 헤더
@implementation LiveActivityManager
+ (instancetype)sharedManager {
static LiveActivityManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (void)startLiveActivityWithTrackName:(NSString *)trackName artistName:(NSString *)artistName {
// Swift 코드에서 Live Activity를 시작하는 함수 호출
// startLiveActivity는 Swift 파일에 구현된 함수입니다.
//
[[SwiftLiveActivityController sharedController] startLiveActivityWithTrackName:trackName artistName:artistName];
}
- (void)updateLiveActivityWithPlaybackTime:(NSTimeInterval)playbackTime isPlaying:(BOOL)isPlaying {
// Swift 코드에서 Live Activity를 업데이트하는 함수 호출
[[SwiftLiveActivityController sharedController] updateLiveActivityWithPlaybackTime:playbackTime isPlaying:isPlaying];
}
- (void)endLiveActivity {
// Swift 코드에서 Live Activity를 종료하는 함수 호출
[[SwiftLiveActivityController sharedController] endLiveActivity];
}
@end
2-2. Swift 코드 (핵심 로직)
위 Objective-C 코드에서 호출할 Swift 코드를 작성해야 합니다. 이 코드는 실제로 Live Activity를 생성하고 업데이트하며 종료하는 역할을 합니다
// SwiftLiveActivityController.swift
import Foundation
import ActivityKit
@objc class SwiftLiveActivityController: NSObject {
static let sharedController = SwiftLiveActivityController()
var activity: Activity<MyActivityAttributes>?
@objc func startLiveActivity(trackName: String, artistName: String) {
let initialAttributes = MyActivityAttributes(trackName: trackName, artistName: artistName)
let initialStatus = MyActivityStatus(playbackTime: 0, isPlaying: true)
do {
activity = try Activity.request(attributes: initialAttributes, contentState: initialStatus, pushType: nil)
print("Live Activity started: \(String(describing: activity?.id))")
} catch {
print("Error starting Live Activity: \(error.localizedDescription)")
}
}
@objc func updateLiveActivity(playbackTime: TimeInterval, isPlaying: Bool) {
guard let activity = self.activity else { return }
let updatedStatus = MyActivityStatus(playbackTime: playbackTime, isPlaying: isPlaying)
Task {
await activity.update(using: updatedStatus)
}
}
@objc func endLiveActivity() {
guard let activity = self.activity else { return }
Task {
await activity.end(dismissalPolicy: .immediate)
}
}
}
이러한 구조를 통해, Objective-C로 작성된 기존 앱 코드베이스를 유지하면서도 Dynamic Island 연동에 필요한 Live Activities 기능을 효과적으로 구현할 수 있습니다.
'ios 앱 개발' 카테고리의 다른 글
| Firebase Crashlytics로 유저 에러 기록 (3) | 2025.08.04 |
|---|---|
| iOS 앱과 Firebase Crashlytics 연결하기 (4) | 2025.07.29 |
| MTS 내 인사이더(A/B Test) 적용 (12) | 2025.07.16 |
| APNs(Apple Push Notification Service) 정리 (2) | 2025.07.15 |
| Objective-C 기본 개념 (3) | 2025.04.21 |