티스토리 뷰

iOS

iOS ) UIMenuController

Zedd0202 2018. 10. 13. 18:21
반응형


안녕하세요 :) Zedd입니다.

UIMenuController라는걸 몰라서 공부해보려고 합니다. 하핫

근데 요새 페이스북에서 유입이 갑자기 많은데, 혹시 어디서....들어오시나요. 

원래 페이스북에서는 안들어오는데 갑자기 많아져서.. 궁금해서....ㅎ;; 알려주시면 감사하겠습니댜


암튼 UIMenuController 공부 고



UIMenuController



이거 들어보셨나요!?!?!?!????!?!?!?!?!?!??!?!!?!?!?

저만 몰랐나요 진짜?????^_ㅠ...공부해야할게 너무나도 많군

요새 제가 Text Programming Guide for iOS를 공부중인데, 여기서


이게 나오길래 오,..이게 어케만드냐 했는데

이것을 바로  UIMenuController로 만드는 것이었습니닷...!



잘 모르시겠다면...



이건 아시겠죠!??!

이것이 바로 UIMenuController입니다.

암튼 일단 문서 고



UIMenuController는 잘라내기(Cut), 붙혀넣기(Copy&Paste), 선택(Select), 모두선택(Select All), 삭제 명령의 메뉴 인터페이스입니다.

싱글톤 UIMenuController 인스턴스를 editing menu라고 합니다.

이 메뉴를 볼 수 있게 하면, UIMenuController는 화면(screen)의 타겟 사각형을 기준으로 위치를 지정합니다.

이 사각형은 대게 선택(selection)을 정의합니다. 

메뉴는 타켓 사각형 위에 나타나거나 공간이 충분하지 않은 경우 그 아래에 나타납니다. 



메뉴 포인터는 


타켓 사각형에 적절하게 배치됩니다. 메뉴를 표시하기 전에 tracking rectangle?을 설정하세요. 또한 선택 항목을 detecting, tracking, displaying할 책임이 있습니다.


tracking rectangle이 모지..

UIResponderStandardEditActions비공식 프로토콜은 사용자가 메뉴 명령을 누를 때 호출되는 메소드를 선언합니다.

UIResponder의  canPerformAction(_:withSender:)메소드는 편집 메뉴와도 관련이 있습니다. responder는 이 메소드를 구현하여 메뉴가 표시되기 전에, 편집 메뉴의 명령을 활성화 및 비활성화 합니다. update()메소드를 호출하여 메뉴 명령의 활성화 상태를 강제로 업데이트 할 수 있습니다.

menuItems프로퍼티를 통해 나만의 메뉴 항목을 제공 할 수도 있습니다. 메뉴 항목을 수정하면, update()메소드를 통해 메뉴 디스플레이를 강제로 업데이트 할 수 있습니다. 


여기까지가 문서 내용인데요, 한번 만들어봅시다.

ㅋㅎ...진짜 별거 없음...

증맬 간단히 만들어 볼게요.

일단 UIMenuController는 싱글톤이기 때문에 



shared를 이용합시다.

일단 View를 하나 추가해줍니다. 뭐 imageView든 뭐든..상관은 없으니 알아서들 추가해주셈

그리고 저는..LongPress -> UIMenuController가 뜬다! 라는 시나리오를 가지고 만들어서..UILongPressGestureRecognizer를 view에 추가해줍니다. 



let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(targetViewDidPress))

longPressGestureRecognizer.minimumPressDuration = 0.5

self.targetView.addGestureRecognizer(longPressGestureRecognizer)



일단 자 여러분 우리가 UIMenuController를 만들잖아요 지금?

그럼 일단 모가 필요할까요???


저 메뉴들이겠죠!?!?!

일단 저 메뉴를 만들어줍니다. 

그냥 거의 UIAlertController와 비슷하다고 생각하시면 됩니다. UIMenuController에도 



UIMenuItem이라는 것이 있어요!

init역시 직관적입니다.



걍 메뉴 이름이랑 ㅇㅇ 이 메뉴 누르면 어떤 action할건지 selector만 넣어주면되는 부분;;;

어케어케 만들어줍니다.


 let zeddMenuItem = UIMenuItem(title: "Zedd", action: #selector(zeddDidTap))


let alanMenuItem = UIMenuItem(title: "Alan Walker", action: #selector(alanDidTap))


머 저는 이렇게 만들어줄게요. 그리고 이걸 넣으면 됨


UIMenuController.shared.menuItems = [zeddMenuItem, alanMenuItem]


와 너무 쉽다 그쵸


그리고 이제 하나 해주어야 하는 작업이 있습니다. 

바로 

setTargetRect(_:in:)이라는 메소드를 호출해줘야하는데요. 

이 setTargetRect(_:in:)을 잠깐 보도록 할게요. 


일단 정의는 이런데요, setTargetRect(_:in:)은 

editing menu가 위치한 view 위(above) 또는 아래에(below) 영역(area)을 설정합니다.


파라미터로는 2개를 받죠?

targetRect와 targetView.


targetRect는 메뉴 명령의 대상이 될 영역을 정의하는 사각형이에요. 즉!!! 우리의 저 파란View라고 할 수 있죠. 이건 이해 가시죠?>?


targetView는 위 targetRect가 나타나는 View에요. 지금 제가 하는 예제에서는 superView가 되겠네요.


targetRect(= target rectangle)은 일반적으로 선택영역의 bounding rectangle입니다.(경계 사각형..?)

~ 위 UIMenuController설명하면서 했던 내용들...~

target rectangle의 너비 또는 높이를 0으로 만들면 UIMenuController는 대상 영역을 위치 지정을 위한 선이나 점으로 간주합니다.

일단 설정이 되면 target rectangle는 view를 추적(track)하지 않습니다. view가 움직이는 경우(스크롤 view처럼), target rectangle을 그에 따라 업데이트 해야합니다.



UIMenuController.shared.setTargetRect(self.targetView.frame, in: self.targetView.superview!)


마지막에 superview를 강제언래핑한건 봐주세여 

guard로 빼주려고 했는데 targetView의 superView를 넣어줘야한다는 것을 알려드리고 싶었음..

아무튼 그렇스빈다.

self.view.superview <는 안됩니다 ㅠ window가 리턴되기 때문



UIMenuController.shared.setMenuVisible(true, animated: true)


그리고 이제 메뉴를 visible하게 만들어줍니다.


+ ) 추가 setTargetRect와 setMenuVisible은 iOS13에서 deprecated되었네요.

DeploymentTarget이 iOS13이상이신 분들은

UIMenuController.shared.showMenu(from:, rect: )

를 이용해주세요. 



자 그리고 이제 실행해보면

아무리 길게 눌러도 editing menu가 안뜨는 것을 볼 수 있어요 ^^1!!!!!!!!!!!!


2가지 작업을 해줘야 하는데요.


1. target View에 becomeFirstResponder()를 호출. 

== targetView를 window의 first responder로 만들어줌.


2. canBecomeFirstResponder를 true를 리턴하도록.


이 둘중 한가지라도 안해주면;; editing menu가 안뜨더라구요. 근데 2번은 도대체 왜 해줘야 하는지 모르겠음ㅡㅡ 알아서 true리턴시켜줘야 하는거 아녀? 1번 하면?


1번부터 해줍시다. 



self.targetView.becomeFirstResponder()


longPressGestureRecognizer의 selector안에서 becomeFirstResponder()를 호출해줍니다.


2번 


self.targetView.canBecomeFirstResponder = true


가 되면 참 좋을텐데요.... canBecomeFirstResponder는 get-only이기 때문에 위 코드는 에러가 납니다. ^_ㅠ


class ZeddView: UIView {

    override var canBecomeFirstResponder: Bool {

        return true

    }

}


이렇게 UIView를 상속받아 커스텀 UIView를 만들고,

아까 우리가 추가했던 view가 이 ZeddView타입이 되도록 해주세요. 


이렇게만 해주면..!!!

이게 아주 잘 나오는 것을 볼 수 있습니다 XD



장난을 쳐보면


이렇게 많이 넣어주면 어케되냐


이렇게 되네요. 

근데 메뉴 포인터가 왜 저렇게 뜨지 ㅎ 바로 위에 안뜨고..!!


장난 둘

target rectangle의 너비 또는 높이를 0으로 만들면 UIMenuController는 대상 영역을 위치 지정을 위한 선이나 점으로 간주합니다. < 이거 해보겠음

처음에 button없이 너비를 0으로 만들었는데, 누를 view가 없어서 1초 당황

정신이 없죠 제가




아무튼 UIMenuController에 대해서 공부해봤습니다.

메모장을 많이 쓰고 이 editing menu도 많이 쓰는데, 이걸 내가 코드로 사용 할 수 있다는 사실조차를 인식못했었음...

머리 아픈 내용이 아니어서 좋네요 ㅎㅎ...

다들 주말 잘 보내세요 XD

반응형