UIActivityViewController를 SwiftUI로
히스토리
- 2022.05.31
- 쿠링 사이드에서 공유하기 기능을 SwiftUI에서 사용하기 위한 포스팅
- 2024.12.11
- 해당 포스팅보다 더 좋은 방법을 발견하여 링크 추가
개선한 방법
해당 포스팅보다 더 좋은 방법을 발견하여 링크 추가
이번 제목도 UIKit스러움
이전에도 말했지만, 프로젝트에서 UIKit을 SwiftUI로 코드롤 전환하고 있는데 여기서 만난 문제를 해결하고자 내가 구글링한 단어 그대로 작성했다.
🟠 ActivityItem
import UIKit
/// `activitySheet` modifier 를 통해 `ActivityView`를 띄울 때 사용하는 activity
struct ActivityItem {
var items: [Any]
var activities: [UIActivity]
var excludedTypes: [UIActivity.ActivityType]
/// - Parameters:
/// - items: `UIActivityViewController` 를 통해 공유할 아이템
/// - activities: 시트에 포함시키고자 하는 커스텀 `UIActivity`
init(
items: Any...,
activities: [UIActivity] = [],
excludedTypes: [UIActivity.ActivityType] = []
) {
self.items = items
self.activities = activities
self.excludedTypes = excludedTypes
}
}
🟠 ActivityView
import SwiftUI
import LinkPresentation
import CoreServices
struct ActivityView: UIViewControllerRepresentable {
@Binding var item: ActivityItem?
var permittedArrowDirections: UIPopoverArrowDirection
var completion: UIActivityViewController.CompletionWithItemsHandler?
init(
item: Binding<ActivityItem?>,
permittedArrowDirections: UIPopoverArrowDirection,
onComplete: UIActivityViewController.CompletionWithItemsHandler? = nil
) {
_item = item
self.permittedArrowDirections = permittedArrowDirections
self.completion = onComplete
}
func makeUIViewController(context: Context) -> ActivityViewControllerWrapper {
ActivityViewControllerWrapper(
item: $item,
permittedArrowDirections: permittedArrowDirections,
completion: completion
)
}
func updateUIViewController(_ controller: ActivityViewControllerWrapper, context: Context) {
controller.item = $item
controller.completion = completion
controller.updateState()
}
}
final class ActivityViewControllerWrapper: UIViewController {
var item: Binding<ActivityItem?>
var permittedArrowDirections: UIPopoverArrowDirection
var completion: UIActivityViewController.CompletionWithItemsHandler?
init(
item: Binding<ActivityItem?>,
permittedArrowDirections: UIPopoverArrowDirection,
completion: UIActivityViewController.CompletionWithItemsHandler?)
{
self.item = item
self.permittedArrowDirections = permittedArrowDirections
self.completion = completion
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMove(toParent parent: UIViewController?) {
super.didMove(toParent: parent)
updateState()
}
func updateState() {
let isActivityPresented = presentedViewController != nil
if item.wrappedValue != nil {
if !isActivityPresented {
let controller = UIActivityViewController(
activityItems: item.wrappedValue?.items ?? [],
applicationActivities: item.wrappedValue?.activities
)
controller.excludedActivityTypes = item.wrappedValue?.excludedTypes
controller.popoverPresentationController?.permittedArrowDirections = permittedArrowDirections
controller.popoverPresentationController?.sourceView = view
controller.completionWithItemsHandler = { [weak self] (activityType, success, items, error) in
self?.item.wrappedValue = nil
self?.completion?(activityType, success, items, error)
}
present(controller, animated: true, completion: nil)
}
}
}
}
아래 코드도 꼭 넣어주세요!
import SwiftUI
extension View {
/**
관련`ActivityItem`이 존재할 때, 해당하는 activity sheet를 보여줍니다.
- Parameters:
- item: activity에 사용할 아이템입니다.
- onComplete: sheet가 dimiss되었을 때, 결과과 호출됩니다.
*/
func activitySheet(_ item: Binding<ActivityItem?>, permittedArrowDirections: UIPopoverArrowDirection = .any, onComplete: UIActivityViewController.CompletionWithItemsHandler? = nil) -> some View {
background(ActivityView(item: item, permittedArrowDirections: permittedArrowDirections, onComplete: onComplete))
}
}
✅ 사용법 (Usage)
import SwiftUI
struct ActivityTestView: View {
@State private var item: ActivityItem?
var body: some View {
Button {
item = ActivityItem(
items: "This will be shared"
)
} label: {
Text("Share")
}
.activitySheet($item)
}
}
마지막으로 present된 것이 중간 그리고 맨 윗부분까지 올라오는 것을 볼 수 있다.
'project > Kuring(공지알림)' 카테고리의 다른 글
[iOS] SPM 프로젝트 이름 변경시 오류 (0) | 2022.08.24 |
---|---|
[git] Git-flow 전략과 프로젝트 예시(feat. Kuring) (2) | 2022.06.10 |
[SwiftUI] List accessory (feat. disclosure indicator) (0) | 2022.05.31 |
[SwiftUI] List Row 선택하기(TableView didSelectRow) (0) | 2022.05.30 |
[iOS] Thread 1: "Attempt to insert non-property list object () for key ~ (0) | 2022.05.05 |