2025. 1. 22. 19:40ㆍUIKit, SwiftUI, H.I.G
클립보드 (Clipboard)는 데이터를 임시로 저장하는 메모리 공간입니다.
보통 텍스트, 이미지, URL 등의 데이터를
복사 (Copy), 잘라내기 (Cut), 붙여넣기 (Paste) 기능으로 앱 간에 공유하고자 할 때 사용되는 임시 저장 공간의 느낌이죠.
일반적으로 아래 화면처럼, 외부에서 복사해온 데이터를 내부에서 붙여넣고자 할 때 사용되는데요. 이번 글에서는 해당 기능을 구현하기 위한 로직을 소개해보고자 합니다!
*링크 저장 서비스인 <토스터 TOASTER>에서는 외부에서 복사해온 링크, 즉 URL을 사용자가 손쉽게 저장할 수 있도록 해당 기능을 구현하게 되었습니다.
UIPasteboard?
💡 An object that helps a user share data from one place to another within your app, and from your app to other apps. (앱 내의 한 곳에서 다른 곳 또는 앱 간 데이터를 공유하는데 도움을 주는 객체입니다.)
UIPasteboard는 iOS 3.0이상부터 지원하는 클래스로, 쉽게 말해 iOS 개발에서 클립보드 데이터를 관리하도록 만들어진 객체입니다.
일반적으로는 UIPasteboard.general 코드를 사용해서 클립보드에 접근하고,
문자열 (String), 이미지 (UIImage), 링크 (URL), 색상 (UIColor)까지 다양한 데이터를 복사/붙여넣기 기능에 활용할 수 있도록 지원하고 있습니다.
iOS 14부터 보안을 위해 Apple에서는,
다른 앱에서 Pasteboard에 저장된 데이터를 받을 때, 위와 같은 복사/붙여넣기 허용 Alert를 자동으로 표출하는 조치를 하고 있다 해요!
즉, 별도의 Alert를 직접 만들어주지 않아도 복사/붙여넣기 허용 Alert는 Apple에서 기본으로 제공해준다는 얘기입니다.
Pasteboard에 대한 시나리오 설계
그냥 코드를 짜기에 앞서서 사실, 사용자가 복사/붙여넣기 기능을 활용하는 시나리오에 대한 설계가 먼저 필요했습니다.
아무런 설계 없이 그냥 앱에서 붙여넣기 기능 (Paste)가 가능하도록만 구현한다면,
위에서 말했던 Alert가 앱이 실행될 때마다 무한으로 표출된다거나 / 사용자가 Paste된 url 데이터를 제대로 활용하지 못하는 문제가 생길 수 있기 때문이죠.
특히, 중요한 것은 "복사해 온 url 데이터를 어느 시점에 초기화 시켜줄 것인가"에 대한 고민이었어요!
1. 최초 복사해 온 url이 자동으로 embed 되면, 초기화를 시켜줘야 할까?
2. 사용자가 [붙여넣기 허용 안 함]을 Alert에서 클릭했을 때, 해당 데이터는 남겨둬야 할까? 초기화시켜야 할까?
3. Pasteboard 상의 url 데이터는 앱 생명 주기의 어느 시점까지 유용하게 남겨야 하는 것일까?
조금 더 자세하게는 위와 같은 내용들을 함께 고민하게 되었고, 결국 아래와 같은 Pasteboaed 시나리오를 세우게 되었습니다.
1. 모든 Pasteboard의 url 데이터는 (방식과 상관없이) 링크 입력칸에 입력되면, 초기화한다.
- 붙여넣기 "허용" 선택 시 -> 자동으로 링크 입력이 이루어지기 때문에 클립보드 초기화 진행!
- 붙여넣기 "허용 안 함" 선택 시 -> 클립보드 상에는 데이터 유지, 이후 사용자가 직접 링크 입력칸에 LongPress 액션으로 [붙여넣기] 행위를 할 수 있음. -> 단, [붙여넣기] 행위 이후에는 클립보드 초기화 진행!
2. Pasteboard의 데이터는 앱이 비활성화되거나, 종료되기 전까지만 유용하도록 한다.
- 만약, 복사된 데이터를 입력하는 사용자의 [붙여넣기] 행위 없이 앱이 종료가 되더라도, 해당 클립보드 데이터는 초기화한다.
3. Pasteboard에 저장되는 url 데이터는 가장 최신의 데이터를 기준으로만 남긴다.
SceneDelegate - sceneWillEnterForeground
앱이 백그라운드에서 포그라운드로 전환되는 시점의 코드입니다.
로그인 여부 (isLoggedIn)와 함께 / UIPasteboard.general.url 코드로 현재 클립보드에 복사되어 있는 URL 값이 있는지를 확인합니다.
만약 값이 있다면, 링크 입력되는 화면 (AddLinkViewController가 해당)으로 전환을 진행하고,
그와 동시에 Pasteboard에 저장되어 있는 url을 absoluteString을 사용해 String 값으로 변환해 전달하고 있는 코드가 있네요.
/// SceneDelegate
func sceneWillEnterForeground(_ scene: UIScene) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
if let pasteboardUrl = UIPasteboard.general.url, isLoggedIn {
guard let rootVC = window?.rootViewController as? ToasterNavigationController else { return }
let addLinkViewController = AddLinkViewController()
rootVC.pushViewController(addLinkViewController, animated: true)
addLinkViewController.embedURL(url: pasteboardUrl.absoluteString)
if let presentedVC = rootVC.presentedViewController {
presentedVC.dismiss(animated: false)
}
}
}
embedURL(url:)
VC에서 URL을 String으로 전달받은 메서드 부분을 조금 더 자세하게 살펴보겠습니다.
- textField.becomeFirstResponder() : 키보드를 최초부터 올리기 위한 텍스트필드 포커스 설정
- textField.text = url : 메서드 파라미터로 전달받은 URL을 해당 텍스트 필드에 자동으로 입력되도록 함. ViewModel에도 동시에 상태 전달
- UIPasteboard.general.url = nil : 클립보드 URL 데이터 초기화하기
특히, Pasteboard 데이터를 설정하는 메서드를 VC에 집어넣음으로써,
만약 사용자가 Long Press 액션을 통해 해당 데이터를 직접 [붙여넣기]하는 경우에도 해당 메서드를 사용하도록 하여, 클립보드의 초기화 시나리오를 준수하도록 만들 수 있었죠!
extension AddLinkViewController {
func embedURL(url: String) {
addLinkView.linkEmbedTextField.becomeFirstResponder()
addLinkView.linkEmbedTextField.text = url
viewModel.embedLinkText.send(url)
UIPasteboard.general.url = nil // 클립보드 초기화!
}
}
SceneDelegate - sceneDidlEnterBackground
앱이 포그라운드에서 백그라운드로 전환될 때,
다시 말해 앱이 비활성화되거나 종료될 때는 시나리오에 의해 별도로 Pasteboard 값을 초기화하는 코드를 추가했습니다.
/// SceneDelegate
func sceneDidEnterBackground(_ scene: UIScene) {
UIPasteboard.general.url = nil
}
완성!
생각보다 짧은 코드로 기능을 구현할 수 있었네요!
오늘 글은 여기서 마무리입니다 :) 궁금한 내용이나, 더 설명이 필요한 사항이 있으면 댓글로 남겨주세요 😊
'UIKit, SwiftUI, H.I.G' 카테고리의 다른 글
[UIAlertController] 강제 업데이트 및 사용성 개선 업데이트 Alert 표출하기 (0) | 2025.01.22 |
---|---|
[UIActivityViewController] 우리 앱에 "공유하기" 기능 (Share Sheet) 구현하는 방법 (1) | 2024.12.23 |
[UIKit] UISheetPresentationController를 사용해서 바텀시트(Sheets)를 만들어보자 (1) | 2024.08.30 |
[iOS] 키보드 레이아웃을 가져오는 개선된 방법 (NotificationCenter to Keyboard Layout Guide) (3) | 2024.08.28 |
[UIHostingController] UIKit 프로젝트에서 SwiftUI 적용해보기 (0) | 2024.08.07 |