[iOS] SwiftUI에서 클립보드 복사하기

Sehee·2024년 7월 21일

iOS 개발하기

목록 보기
9/16
post-thumbnail

시작하며,

지난 포스트에서 피드백을 받기 위해 앱 내에서 메일을 전송할 수 있도록 기능을 구현했었다

지난 포스트 : [iOS] 앱에서 메일 보내기 (feat. MessageUI)

그러나 앱에서 메일 발송을 실패한 경우를 대비하여 추가 장치가 필요한 상황이었고, 그 장치로 외부 메일 앱에서 메일을 전송할 수 있도록 이메일 주소 복사 기능을 추가하게 되었다


버튼 클릭 시 클립보드 복사

간단하게 아래처럼 복사 아이콘을 클릭하면 클립보드에 복사되도록 구현하고자 한다

코드 요약

간략히 적어보겠다

import SwiftUI

struct ContentView: View {
	
    // ... 변수 선언
    
	var body: some View {
    	HStack {
        
        	// ... UI 그리기
            
            // 복사 버튼
			Button(action: {
            
				// ... 버튼 이벤트
                copyToClipboard(...)
			}, label: {
				Image(systemName: "square.on.square")
					.foregroundStyle(.gray)
					.font(.system(size: 16))
			})
        }
        .alert(...) { ... }
    }
    
    func copyToClipboard(_ text: String) { ... }
}

enum ClipboardCopyStatus { ... }

복사 기능 추가하기

변수 선언

복사할 텍스트는 변수로 지정해준다
기타 필요한 변수도 모두 선언해주자

let textToCopy: String = "복사할 텍스트"

copyToClipboard 함수

복사 기능은 사실 UIPasteboard.general.string = text 한줄이면 구현 가능하다
그러나 여러 상황에 따라 예외가 발생할 수 있으므로 예외처리도 함께 해주었다

func copyToClipboard(_ text: String) {
    
    // 문자열이 비어있는 경우 예외처리
    guard !text.isEmpty else {
        return
    }

    if UIPasteboard.general.hasStrings {
        // 복사 성공
        UIPasteboard.general.string = text
    } else {
        // 접근 권한 없어 복사 실패
    }
}

버튼에 함수 연결

간단하게, 버튼 액션 부분에 함수를 호출해주면 된다

Button(action: {    
	// ... 버튼 이벤트
	copyToClipboard(textToCopy)
}, label: { ... }

alert창 띄우기

복사가 되는 거까진 구현했는데, 사용자 입장에서는 복사 여부를 알 수 없는 불편함이 있어보인다
따라서, 복사 상태에 따라 alert창을 띄워주겠다

열거형으로 복사 상태 정의

케이스에 따라 alert창의 문구가 달라져야 하기에 열거형으로 복사 상태를 미리 정의해두었다

enum ClipboardCopyStatus {
    case success
    case emptyString
    case failAccess

    var message: String {
        switch self {
        case .success:
            return "클립보드에 복사되었습니다!"
        case .emptyString:
            return "클립보드 복사에 실패했습니다"
        case .failAccess:
            return "클립보드 복사에 실패했습니다\n설정에서 권한을 확인해주세요"
        }
    }
}

변수 선언

// 변수 선언
@State var showCopyAlert: Bool = false
@State var alertMessage: String = ""

alert창 추가

// 복사 버튼
Button()
.alert(isPresented: $showCopyAlert) {
	Alert(title: Text("알림"), message: Text(alertMessage), dismissButton: .default(Text("확인")))
}

copyToClipboard 함수 수정

copyToClipboard 함수에서 예외 상황에 따라 alertMessage를 변경한다
(그냥 코드 복붙해도 됨)

func copyToClipboard(_ text: String) {
    
    // 문자열이 비어있는 경우 예외처리
    guard !text.isEmpty else {
        alertMessage = ClipboardCopyStatus.emptyString.message
        showCopyAlert = true
        return
    }

    if UIPasteboard.general.hasStrings {
        // 복사 성공
        UIPasteboard.general.string = text
        alertMessage = ClipboardCopyStatus.success.message
    } else {
        // 접근 권한 없어 복사 실패
        alertMessage = ClipboardCopyStatus.success.message
    }
    showCopyAlert = true
}

마치며,

웹에서는 라이브러리 사용해서 구현할 수 있었고, 구현하는데에도 꽤나 시행착오를 겪었던 기억이 있다
그러나 앱에서는 코드 한 줄로 완성이라 너무 편하다 (비록 예외처리 하느라 꽤 길어졌지만...)

profile
디자인하는 개발자

0개의 댓글