내용이 길어서 일단 결론부터 말하자면 가능함 그리고 플러터는 개쩌는 킹갓 프레임워크임.

ios 16이후부턴 ios의 보안정책이 강화되어서 클립보드에서 붙여넣기에 대해 제한이 훨씬 빡세졌음 

최근 1년 이내에 ios를 평소에 사용한사람이라면 이 프롬프트, 알림창을 본적이 있을거임

ios어플리케이션에서 프로그래밍 방식으로 클립보드에서 다른 프로그램에 있는 데이터를 사용하려하면 나타나는 프롬프트인데

허용하면 어플리케이션은 데이터를 얻는거고 불허하면 nil,null 값을 전달함 

애플이 이러한 제한을 건 이유는 나름대로 납득은 감 이전의 ios, 그리고 그 외의 현재까지 운영체제들은 프로그램이 클립보드를 읽는것에 대해 자유롭게 두고있음 심지어 따로 버튼을 누르지 않아도 일단 읽어버리는것도 있고 오히려 그걸 이용해서 편의성을 제공하려는 어플도 있음 

최근의 모바일에서는 프로그램이 클립보드를 읽으면 클립보드에서 붙여넣기 했다는 토스트 알림을 띄움(안드로이드, ios 공통사항), 구글은 이정도 조치까지만 한거지만 애플은 이걸로 부족하다고 판단함 만약 클립보드에 있었던 내용이 어딘가 로그인할때 쓰던 암호였고 다른데서 실행시킨 어플이 자동적으로 클립보드를 읽어버리면 알림을 띄워봤자 이미 늦는다는거임 그 어플에서 자기네서버로 보내든 지지고 볶든 막을수가없지 그래서 애플은 프로그래밍적으로 클립보드에 접근하려 하면 운영체제에서 일단 막는 조치를 추가함

이러한 알림은 다른 어플에서 복사했다가 사용할 어플에서 그어플에서 자체적으로 구현한 붙여넣기 방법을 사용할때마다 매번뜸 그때 허용했다고 해서 다음에 안뜨는게 아님 16.0버전 초에는 이걸 버그로 생각하는 사람들도 많았음 머 실제로 약간 버그인 부분도 있었는데(UIPasteControl로 붙여넣어도 프롬이 뜨는부분, 지금은 고쳐짐) 허용했는데 다음 또 뜨는건 버그가 아니라 애플이 일부러 그렇게 만든거임

ios 크롬인데 자체적으로 만든 붙여넣기 버튼(?)을 사용하려하면 매번 어플의 라이프사이클을 중지시키고 프롬창을 띄움

이러한 제한은 ios네이티브앱도 해당이고 리액트네이티브든 플러터든 이걸 우회할수 없음.. 

메모앱 만들었는데 붙여넣기 팝업매법뜨면 별점1점 먹고 저 나락으로 추락하는거임 

이걸 설정에서 끌수는있는데 사용자들은 그렇게 인내심이 많지가 않음


근데 ios에서 붙여넣기가 프롬이 뜨지않고 바로 붙여넣기 되는경우를 경험한 경우도 있을거임

애플은 프롬팝업 없이 붙여넣기가 허용될수있는 방법 3가지를 제공함

1. 텍스트필드에서 editmenu를 사용해서 붙여넣기

이거임 사용자가 붙여넣겠다는 행동이 명확하기때문에 팝업없이 붙여넣기가됨

2.키보드 붙여넣기 단축키, (맥에서 커맨드+v)를 누름

3.UIPasteControl을 구현한 버튼을 누름


3가지 방법모두 애플의 네이티브앱에서 구현할수있고 1,2번은 별다른 적용없이도 작동함

3번이 중요한데 SwiftUI로 네이티브 앱을 만든다면 PasteButton을 사용하게됨 

UIPasteControl로 버튼을 만들면 죄다 거의 같은 모양의 버튼이 나옴 커스텀이 상당히 제한적임

그만큼 사용자가 확실히 붙여넣기 버튼 이라는걸 인지할수 있어야 함을 강조하고있음 

이것또한 네이티브에서 딱히 어려움 없이 적용할수있음


자 이제 문제는 멀티플랫폼을 지원하는 프레임워크들임 

리액트 네이티브와 플러터가 대표적인데 애네들은 저 허용사항이 적용될수있을까?

일단 1번 2번 같은 경우엔 1번이 된다면 2번이 가능하게 될수밖에 없음 

즉 ios의 네이티브의 텍스트필드를 사용한다면 문제가 없음

리액트네이티브부터 살펴보자면

리액트네이티브는 RN의 자바스크립트 엔진이 컴포넌트를 가져와서 배치하기 때문에 

그냥 텍스트필드를 사용하면 그게 네이티브 텍스트필드가 됨 그래서 editmenu 사용하는데 문제가없음

그럼 3번에 대해서는 어떨까

https://docs.expo.dev/versions/latest/sdk/clipboard/#clipboardpastebutton

expo에서 제공하는 컴포넌트가 있는데 expo가 악마와의 거래 수준으로 장단점이 커서 안써봐서 실험은 못해봄 

일단 사용은 가능한듯... react native cli에서 expo컴포넌트만 따로 빼와서 작동 가능한지는 모르겠네


이제야 본 주제인 플러터인데 

일단바로 이야기 하자면 플러터의 cupertino위젯으로는 1,2,3 전부 불가능함

생긴거는 ios의 네이티브 컴포넌트하고 똑같이 생기고 cupertino 텍스트필드에선 editmenu도 똑같이뜨는데 왜 안되냐면

그냥 진짜 똑같은 모양으로 만든거라 그럼 

editmenu에서 붙여넣기 누르거나 붙여넣기 단축키 눌러도 내부적으로 프로그래밍방식으로 클립보드에 접근함

그래서 붙여넣기할때마다 아주 킹받는 프롬프트팝업이 뜸...

플러터 진짜 다 좋은데 이거 때문에 허접 gui호소인 이라고 생각하고 해결책을 찾기전 일주일동안 리액트 네이티브랑 swiftui 공부했엇음 

하지만 swiftui 파다보니까 플러터의 비록 코드길이 200배지만 명확하게 확실하게 돌아가는 setState()하고 

패키지들의 개쩌는 생산성이 너무나도 그리워짐 그리고 리액트 네이티브 너무 킹받음 뭐 하나 패티지 설치할때마다 노드 버전지원에 문제있거나 xcode에서 추가적으로 만져줘야하는게 많다...

그래서 플러터를 어캐 살려볼수없을까 해서 Platform Views를 연구하기 시작함

https://docs.flutter.dev/platform-integration/ios/platform-views

이거를 기반으로 uipastecontrol를 uiview에 배치시키기로함

https://developer.apple.com/documentation/uikit/uipastecontrol

애플문서대로 uipastecontrol를 사용해서 버튼을 만들고 띄웠는데 잘됨.... 이라고 생각했었는데 디버그에선 잘되는데 릴리즈모드에서 팝업뜸

근데 애플에서 PasteButton라는 swiftui의 버튼이 있어서 그걸 사용해 보기로함

PasteButton를 가진 swiftui의 뷰를 uiview로 이식하고 그 uiview를 플러터 Platform Views를 통해 그려냄

물론 메서드는 메서드 채널을 통해 연결함 결과는 매우 적절히 동작 하였음

남은 문제는 이걸 독립적인 상태를 가진 위젯으로써 작동하게 만들어야 한다는것이었는데 

static으로 선언된 메서드채널을 통해 붙여넣기한 데이터가 이동하는데 너무나도 한계가 있었음 

예를 들어 붙여넣기 버튼이 여러개 있고 각각 쌍으로 있는 텍스트위젯에 내용을 붙여넣기 한다면? 그리고 그러한 쌍이 동적으로 생성 된다면? 

메서드 채널에 동적으로 각쌍의 콜백함수를 할당하는 방법을 사용할수도 있겠지만 구조가 너무 복잡해지는건 둘째치고 

메서드채널은 내부의 메서드들을 switch문으로 실행하는데 다른 실행중인 메서드로 메인쓰레드가 너무나도 바빠지는 문제가 생길수도있음 

만약 메서드 채널에 다른 용도의 자주 실행되는 메서드가 있다면 성능적으로 좋지 않을것 같았음

그래서 구조를 아예 갈아엎어서 메서드 채널 자체를 동적으로 만들자는 결론에 도달 두번째 삽질이 시작되었음 

일단 메인에서 실행되는 메서드채널이 있고 이 채널은 Platform Views의 위젯들이 initState되면 위젯을 만들라는 메서드가 전돨되고 위젯안에 고유한 uuid를 받아서 그 uuid를 매서드체널이름으로 해서 새로운 매서드채널을 만들고 연결해줌 즉 각 위젯마다 고유한 메서드채널이 있는거임 메모리누수에 대한 우려가 있었긴했는데 새로생긴 메서드채널은 플러터의 PlatformViews위젯이 dispose되면 플러터쪽 메서드 채널도 gc되고 플러터쪽 dispose로 인해 swif쪽 FlutterPlatformView도 해제 되면서 그쪽 메서드 체널도 같이 해제 될거라 생각함

 원래 플러터랑 연결되는 네이티브쪽 객체는 시작때 AppDelegate에서 register 메서드로 등록해야하는데 나는 나중에 원할때 쓸수있게 만들어야해서 처음 register메서드가 실행될때 존재하는 registrar를 납치해서 프로퍼티로 고정한다음 나중에 불러다가 동적으로 register를 실행할수있게 만듬 이건 이게 될까? 싶은 생각이 강했는데 되더라고 

릴리즈에서도 완성적으로 작동해서 플러그인으로 만듬 

추가적으로 PasteButton은 백그라운드 상태에서 클립보드 내용이 안쓸거 같다 싶으면 지멋대로 비활성화되어서 아예 포그라운드로 앱이 올라올때 새로 그려지게 만듬


https://pub.dev/packages/native_swiftui_pastebutton_and_textfield

pub에 올렸음 example에 있는거 잘 보고 따라하면 쉬움 

빌드할때 ios16.0이상 무적권 설정해야함